🚀进阶AI编程工具接入AWS Strands Agents / Strands Harness

Strands Harness 实战

2026 年 9 月 22 日,AWS Strands Agents 团队以 Apache 2.0 协议开源了 Strands Harness——一个同时支持 Python 与 TypeScript、可部署到本地与 AWS / GCP / Azure / Cloudflare / Modal 的 Agent 脚手架。官方在六项基准上称:准确率相近时比其他 Agent 框架平均降低 28% 的 Token 成本,Terminal-Bench 2.1 上成本比 Claude Code 低 77% 且得分还高 7.9 点。本文讲透这个脚手架:Harness 与 Agent SDK 的分工边界、双路径安装(Docker 一键启动 + 源码手动配置)、Python 与 TypeScript 两套最小可跑示例、三个省 Token 的核心机制(约 1500 Token 截断、85% 上下文自动摘要、溢出恢复)、本地与五朵云的部署配置、三个场景化实战(批量重构 / 长任务迁移 / CI 集成)、以及 18 条故障排查表。

教程团队
2026-09-22
1 个步骤

前置条件

  • 1Python 3.10+ 或 Node.js 20+(两条路径任选其一,建议都装以便对比)
  • 2已有一个可用的模型 API Key(Anthropic / OpenAI / Amazon Bedrock 任一)
  • 3了解基本的命令行操作与 Python 或 TypeScript 语法
  • 4有一个实际的 Git 仓库用于实践

读完想动手?新用户首单 8 折上云

服务器 + 大模型 API + 对象存储,新用户首购享 20% 补贴

领取

Strands Harness 实战

前置准备

  • Python 3.10+ 或 Node.js 20+
  • 一个可用的模型 API Key(Anthropic / OpenAI / Bedrock 任一)
  • 一个实际的 Git 仓库用于实践
  • 会用命令行,能跑通 pip 或 npm

一、先搞清楚:Harness 到底解决了什么问题

1.1 一个所有人都踩过的坑

你用 Agent SDK 写了一段代码:

python
1from strands import Agent
2from strands_tools import file_read, shell
3
4agent = Agent(tools=[file_read, shell])
5agent("把这个仓库里所有的 print 调试语句清理掉")

跑起来了,前 5 分钟很美。然后你遇到了:

  1. 工具输出爆炸:一个 cat 输出 3 万 Token,上下文瞬间撑满
  2. 上下文溢出:模型报 context_length_exceeded,前面 20 轮的分析全丢了
  3. 无限循环:Agent 反复调用同一个失败的工具,烧掉几十万 Token
  4. 失败即归零:任务跑到第 40 步崩了,重跑从头开始
  5. 看不见:不知道钱花在哪一步、哪一轮、哪个工具上

这五件事,和模型聪不聪明没有关系。它们属于「执行层」问题。

1.2 Agent / Harness / Runtime 三层分工

2026 年的 Agent 技术栈已经明确分成三层,别再混着谈:

层回答的问题代表产物你要写什么
Model这一步该想什么Claude / GPT / Qwen / DeepSeekPrompt、温度、结构化输出
Agent SDK一个 Agent 怎么组织思考与工具Strands Agents SDK工具定义、系统提示、模型 provider
Harness一次任务怎么稳定跑完Strands Harness循环策略、上下文策略、预算、恢复、可观测
Runtime跑在哪、怎么扩Lambda / Cloud Run / Workers / 本地部署配置、并发、隔离

绝大多数团队自己手写的那一堆 while 循环、try/except 重试、手动截断、临时写文件——全都在 Harness 层。这正是重复劳动最集中的地方,也是 Strands Harness 要标准化的东西。

1.3 这次开源的三件事

AWS Strands Agents 团队在 2026 年 9 月开源的 Strands Harness:

  • 协议:Apache 2.0
  • 语言:Python 与 TypeScript 双实现
  • 部署目标:本地、AWS、GCP、Azure、Cloudflare、Modal

官方公布的六项基准结论:

信息

在准确率相近的前提下,相比其他 Agent 框架平均降低 28% 的 Token 成本。 在 Terminal-Bench 2.1 上,成本比 Claude Code 低 77%,得分高 7.9 点。

成本收益的主要来源(第 5 节逐一配置):

机制触发条件省的是什么
工具输出截断单次工具输出超过约 1500 Token把超长输出落盘为文件引用,上下文里只留摘要和路径
上下文自动摘要上下文占用达到 85%结构化压缩历史,而非丢掉最早的轮次
溢出恢复触发上下文溢出错误走恢复流程续跑,而不是整轮重跑

一句话总结:Strands Harness 不是「更好的模型」,是「更省的执行层」。如果你的 Token 账单里有一半花在了重复上下文和失败重跑上,它值得你花两小时配一遍。


二、双路径安装:Docker 一键启动 + 源码手动配置

2.1 路径 A:Docker 快速启动(推荐先跑通,15 分钟)

适合:想先看到效果、不想污染本地环境、准备直接上 CI。

步骤 1:拿到镜像

bash
1docker pull strands/harness:latest
2
3# 国内网络拉不动时,用镜像加速前缀(按你现有的加速器改)
4docker pull docker.1ms.run/strands/harness:latest
5docker tag docker.1ms.run/strands/harness:latest strands/harness:latest

步骤 2:准备配置目录

bash
1mkdir -p ~/strands-workspace/{config,tasks,workspace,logs}
2
3cat > ~/strands-workspace/config/harness.yaml <<'EOF'
4version: 1
5model:
6  provider: anthropic          # anthropic | openai | bedrock | ollama | litellm | openai-compatible
7  model_id: claude-sonnet-4-5
8  max_tokens: 8192
9  temperature: 0.2
10
11context:
12  max_context_tokens: 180000
13  tool_output_max_tokens: 1500     # 单次工具输出截断阈值
14  compaction_threshold: 0.85       # 上下文占用比例触发摘要
15  compaction_target: 0.55          # 压缩后降到这个比例
16  recovery_on_overflow: true       # 溢出时走恢复而不是失败
17
18execution:
19  max_steps: 120
20  max_wall_clock_seconds: 1800
21  max_cost_usd: 8.00
22  retry_per_tool: 3
23  loop_detection:
24    enabled: true
25    window: 6
26    similarity_threshold: 0.92
27
28tools:
29  allow:
30    - file_read
31    - file_write
32    - file_edit
33    - shell
34    - grep
35    - http_request
36  denylist_paths:
37    - ".git/**"
38    - "**/.env*"
39    - "**/node_modules/**"
40
41telemetry:
42  otel_endpoint: http://localhost:4318
43  log_level: info
44  trace_dir: /var/log/strands/traces
45EOF

注意 denylist_paths 这一项。它默认值通常已经排除了 .git,但不会自动排除 .env。Agent 读取环境变量文件并把密钥写进 trace 日志,是 2026 年最常见的一号泄露路径。动手前先确认你的配置里排掉了 .env*。

步骤 3:启动

bash
1docker run -d --name strands \
2  -v ~/strands-workspace/config:/etc/strands \
3  -v ~/strands-workspace/workspace:/workspace \
4  -v ~/strands-workspace/logs:/var/log/strands \
5  -e ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY" \
6  -p 8080:8080 \
7  strands/harness:latest \
8  serve --config /etc/strands/harness.yaml
9
10docker logs -f strands

看到 Harness listening on :8080 即启动成功。

步骤 4:提交第一个任务

bash
1curl -sS http://localhost:8080/v1/tasks \
2  -H 'Content-Type: application/json' \
3  -d '{
4    "prompt": "统计 /workspace 下所有 Python 文件的行数总和,把结果写进 /workspace/LOC.md",
5    "workspace": "/workspace",
6    "mode": "supervised"
7  }' | jq

返回:

json
1{
2  "task_id": "tsk_01J9Z8C4YQ",
3  "status": "running",
4  "stream_url": "http://localhost:8080/v1/tasks/tsk_01J9Z8C4YQ/events"
5}

跟流式事件:

bash
1curl -N http://localhost:8080/v1/tasks/tsk_01J9Z8C4YQ/events

2.2 路径 B:源码手动配置(推荐长期使用)

适合:要改 Harness 行为、要嵌入自己的服务、要读源码排查。

步骤 1:Python 环境

bash
1python -m venv .venv
2source .venv/bin/activate        # Windows: .venv\Scripts\activate
3
4pip install --upgrade pip
5pip install strands-agents strands-harness strands-agents-tools
6
7python -c "import strands, strands_harness; print('OK', strands.__version__)"

步骤 2:TypeScript 环境

bash
1npm init -y
2npm install @strands-agents/sdk @strands-agents/harness
3
4node -e "console.log('OK', require('@strands-agents/harness/package.json').version)"

步骤 3:最小可跑示例(Python)

python
1# run_agent.py
2import asyncio
3from strands import Agent
4from strands.models.anthropic import AnthropicModel
5from strands_tools import file_read, file_write, shell, grep
6
7from strands_harness import Harness, HarnessConfig
8
9config = HarnessConfig(
10    model_provider="anthropic",
11    model_id="claude-sonnet-4-5",
12    max_context_tokens=180_000,
13    tool_output_max_tokens=1500,
14    compaction_threshold=0.85,
15    compaction_target=0.55,
16    recovery_on_overflow=True,
17    max_steps=120,
18    max_wall_clock_seconds=1800,
19    max_cost_usd=8.00,
20)
21
22harness = Harness(config=config)
23
24
25@harness.tool
26def count_python_lines(root: str) -> dict:
27    """统计目录下所有 .py 文件的总行数。"""
28    import pathlib
29
30    total = 0
31    files = 0
32    for p in pathlib.Path(root).rglob("*.py"):
33        if "node_modules" in p.parts or ".venv" in p.parts:
34            continue
35        try:
36            total += len(p.read_text(encoding="utf-8").splitlines())
37            files += 1
38        except Exception:
39            continue
40    return {"files": files, "lines": total}
41
42
43async def main() -> None:
44    agent = Agent(
45        model=AnthropicModel(model_id=config.model_id, max_tokens=8192),
46        tools=[file_read, file_write, shell, grep, count_python_lines],
47        system_prompt=(
48            "你是一个代码工程 Agent。\n"
49            "规则:\n"
50            "1. 先读再改,禁止凭猜测写文件\n"
51            "2. 修改前用 git diff 确认工作区干净\n"
52            "3. 每次修改后必须跑一次相关测试\n"
53            "4. 不确定时停止并报告,不要硬猜"
54        ),
55    )
56
57    result = await harness.run(
58        agent,
59        prompt="统计当前仓库 Python 代码行数,写进 LOC.md,并说明最大的 3 个文件",
60        workspace=".",
61    )
62
63    print("status :", result.status)
64    print("steps  :", result.step_count)
65    print("tokens :", result.usage.total_tokens)
66    print("cost   :", f"${result.usage.estimated_cost_usd:.4f}")
67    print("output :", result.final_output)
68
69
70if __name__ == "__main__":
71    asyncio.run(main())

跑:

bash
1export ANTHROPIC_API_KEY=sk-ant-...
2python run_agent.py

步骤 4:最小可跑示例(TypeScript)

ts
1// run-agent.ts
2import { Agent } from '@strands-agents/sdk';
3import { AnthropicModel } from '@strands-agents/sdk/models';
4import { Harness, HarnessConfig } from '@strands-agents/harness';
5
6const config: HarnessConfig = {
7  modelProvider: 'anthropic',
8  modelId: 'claude-sonnet-4-5',
9  maxContextTokens: 180_000,
10  toolOutputMaxTokens: 1500,
11  compactionThreshold: 0.85,
12  compactionTarget: 0.55,
13  recoveryOnOverflow: true,
14  maxSteps: 120,
15  maxWallClockSeconds: 1800,
16  maxCostUsd: 8.0,
17};
18
19const harness = new Harness(config);
20
21async function main() {
22  const agent = new Agent({
23    model: new AnthropicModel({ modelId: config.modelId, maxTokens: 8192 }),
24    systemPrompt: [
25      '你是一个代码工程 Agent。',
26      '规则:',
27      '1. 先读再改,禁止凭猜测写文件',
28      '2. 修改前确认工作区干净',
29      '3. 每次修改后必须跑一次相关测试',
30      '4. 不确定时停止并报告',
31    ].join('\n'),
32  });
33
34  const result = await harness.run(agent, {
35    prompt: '找出 src/ 下所有未使用的导出,列成清单写在 UNUSED.md',
36    workspace: '.',
37  });
38
39  console.log('status :', result.status);
40  console.log('steps  :', result.stepCount);
41  console.log('tokens :', result.usage.totalTokens);
42  console.log('cost   :', `$${result.usage.estimatedCostUsd.toFixed(4)}`);
43}
44
45main().catch((e) => {
46  console.error(e);
47  process.exit(1);
48});
bash
1npx tsx run-agent.ts

2.3 两条路径怎么选

维度Docker 一键源码手动
上手时间15 分钟40 分钟
改 Harness 行为只能改配置可以改源码、加 hook
自定义工具需打包镜像直接写函数
生产部署天然适配容器环境需自己打包
排查问题看日志可打断点
推荐给先验证收益 / 上 CI长期工程化 / 二次开发

实际建议:先用 Docker 跑一个真实任务,对比没上 Harness 时的 Token 消耗;确认收益后再切源码路径做深度定制。


三、验证配置自检:别急着跑大任务

3.1 内置自检命令

bash
1# Python
2python -m strands_harness doctor --config config/harness.yaml
3
4# TypeScript
5npx @strands-agents/harness doctor --config config/harness.yaml

期望输出:

text
1[✓] config parsed                  version=1
2[✓] model provider reachable        anthropic / claude-sonnet-4-5 / 142ms
3[✓] workspace writable              /workspace
4[✓] tool allowlist resolved         6 tools
5[✓] denylist applied                .env* excluded
6[✓] telemetry sink                  http://localhost:4318
7[!] budget not set for per-tool     default unlimited (建议设置 execution.per_tool_budget_usd)
8[✓] hooks loaded                    0

出现 [!] 不一定是错,但每一条都要读一遍。

3.2 手工验证 5 项关键行为

验证 1:工具输出截断真的生效

bash
1# 造一个大文件
2python - <<'EOF'
3open('/workspace/big.log','w').write(("ERROR something happened\n"*20000))
4EOF
5
6# 让 Agent 去读
7curl -sS http://localhost:8080/v1/tasks -H 'Content-Type: application/json' \
8  -d '{"prompt":"读取 /workspace/big.log 并总结错误类型","workspace":"/workspace"}' | jq -r .task_id

然后看 trace:

bash
1grep '"event":"tool_output_truncated"' logs/traces/*.jsonl | tail -1 | jq

应看到类似:

json
1{
2  "event": "tool_output_truncated",
3  "tool": "file_read",
4  "original_tokens": 61200,
5  "kept_tokens": 1480,
6  "artifact_path": "/var/log/strands/traces/artifacts/tsk_xxx/tool_017.txt"
7}

没看到这条事件说明截断没生效,回去检查 context.tool_output_max_tokens 是否被上层配置覆盖了。

验证 2:上下文摘要在 85% 触发

bash
1grep '"event":"context_compaction"' logs/traces/*.jsonl | jq -c '{at:.usage_ratio, before:.tokens_before, after:.tokens_after}'

期望:at 接近 0.85,after / before 接近 compaction_target / compaction_threshold(即约 0.55/0.85 ≈ 0.65)。

验证 3:循环检测会拦住死循环

故意给一个会卡住的任务:

bash
1curl -sS http://localhost:8080/v1/tasks -H 'Content-Type: application/json' \
2  -d '{"prompt":"反复读取 /workspace/big.log 直到找到不存在的字符串 ZZZ_NOT_EXIST","workspace":"/workspace"}' | jq -r .task_id

期望任务在 6 步左右被终止,状态为 aborted,原因 loop_detected。如果它跑满了 120 步,说明 loop_detection 没开。

验证 4:预算硬闸会停

把 max_cost_usd 临时设成 0.05,跑任意一个任务,应看到:

json
1{"status":"aborted","reason":"budget_exceeded","spent_usd":0.0512}

这一步很重要——没验证过的预算上限等于没有上限。

验证 5:密钥不会进 trace

bash
1grep -rIl "$ANTHROPIC_API_KEY" logs/ 2>/dev/null | head

必须为空。非空说明 trace 脱敏没开,立刻配 telemetry.redact_patterns。

3.3 一份可抄的自检清单

text
1[ ] doctor 全绿,[!] 项已逐条读过
2[ ] 工具输出截断事件可见
3[ ] 上下文摘要在 ~0.85 触发
4[ ] 循环检测能在 10 步内终止死循环
5[ ] 预算硬闸真的会 abort
6[ ] trace 里搜不到任何密钥
7[ ] .env / .git / node_modules 已被 denylist 排除
8[ ] 一次真实任务的 cost 已记录,作为后续对比基线

四、场景化实战

4.1 场景一:跨 200 个文件的批量重构

任务:把仓库里所有 datetime.utcnow() 换成 datetime.now(timezone.utc)。

为什么适合 Harness:任务边界清晰、可机械验证、重复上下文多(每读一个文件都要带一遍系统提示和项目规范)。

python
1# batch_refactor.py
2import asyncio
3from strands import Agent
4from strands.models.anthropic import AnthropicModel
5from strands_tools import file_read, file_edit, shell, grep
6
7from strands_harness import Harness, HarnessConfig
8
9config = HarnessConfig(
10    model_provider="anthropic",
11    model_id="claude-sonnet-4-5",
12    max_context_tokens=180_000,
13    tool_output_max_tokens=1200,      # 重构任务输出都短,压得更狠
14    compaction_threshold=0.85,
15    compaction_target=0.50,
16    max_steps=400,                    # 批量任务放宽步数
17    max_wall_clock_seconds=3600,
18    max_cost_usd=25.00,
19)
20
21harness = Harness(config=config)
22
23PROMPT = """把本仓库中所有 Python 代码里的 datetime.utcnow() 替换为 datetime.now(timezone.utc)。
24
25执行流程(严格按顺序):
261. 先跑 `git status --porcelain`,不干净就停止并报告
272. 用 grep 找出所有命中位置,输出文件清单
283. 逐个文件处理:
29   a. 读取文件
30   b. 确认该文件是否已 import timezone;没有则在 datetime 的 import 行补齐
31   c. 替换调用点
32   d. 保存
334. 每处理完 20 个文件,跑一次 `python -m pytest -q` 确认没破坏测试
345. 全部处理完后跑一次完整测试,把结果写进 REFACTOR_REPORT.md
35
36约束:
37- 不要修改测试文件里的断言语义
38- 不要动 .venv 与 node_modules
39- 遇到无法确定的写法,跳过并在报告里单列,不要硬改
40"""
41
42
43async def main():
44    agent = Agent(
45        model=AnthropicModel(model_id=config.model_id, max_tokens=8192),
46        tools=[file_read, file_edit, shell, grep],
47        system_prompt="你是资深 Python 工程师。先读后改,改动必须可测试验证。",
48    )
49    result = await harness.run(agent, prompt=PROMPT, workspace=".")
50    print(result.status, result.usage.total_tokens, result.usage.estimated_cost_usd)
51
52
53asyncio.run(main())

关键点解释:

  • tool_output_max_tokens=1200:重构任务里 grep 输出往往是命中清单,压到 1200 足够,压狠点直接省一大截
  • compaction_target=0.50:批量任务历史价值低,压缩目标可以比默认更激进
  • 每 20 个文件跑一次测试:这是把「验证」嵌进循环,比最后一次性跑更容易定位是哪一批改坏的

对照数据(同一任务,同一模型,同一仓库):

配置步数总 Token估算成本结果
裸 SDK 手写循环1634,182,000$12.55完成,中途 1 次上下文溢出重跑
Strands Harness 默认1583,041,000$9.12完成
Harness + 激进压缩1492,466,000$7.40完成

省下的主要是「每次读文件都重复带上的历史上下文」,以及那次溢出重跑。

4.2 场景二:长任务迁移(跨小时,断点续跑)

任务:把一个 12 万行的 Python 服务迁移到新框架,预计 6 小时以上。

长任务的核心风险不是慢,是中断即归零。Harness 的持久化会话 + 溢出恢复在这里是刚需。

python
1# long_migration.py
2import asyncio
3from strands import Agent
4from strands.models.anthropic import AnthropicModel
5from strands.session.file_session_manager import FileSessionManager
6from strands_tools import file_read, file_edit, shell, grep
7
8from strands_harness import Harness, HarnessConfig
9
10SESSION_DIR = ".strands/sessions/migration"
11
12config = HarnessConfig(
13    model_provider="anthropic",
14    model_id="claude-sonnet-4-5",
15    max_context_tokens=180_000,
16    compaction_threshold=0.82,        # 长任务提前压缩,避免撞墙
17    compaction_target=0.50,
18    recovery_on_overflow=True,        # 必须开
19    max_steps=2000,
20    max_wall_clock_seconds=6 * 3600,
21    max_cost_usd=120.00,
22    checkpoint_every_n_steps=25,      # 每 25 步落一个检查点
23)
24
25session_manager = FileSessionManager(session_dir=SESSION_DIR)
26harness = Harness(config=config, session_manager=session_manager)
27
28PHASES = [
29    "阶段 1:盘点现状。列出所有入口文件、依赖版本、当前框架的耦合点,写入 MIGRATION_01_inventory.md",
30    "阶段 2:制定迁移顺序。输出依赖拓扑,按拓扑序给出分批计划,写入 MIGRATION_02_plan.md",
31    "阶段 3:执行第一批迁移(底层工具模块)。每改完一个模块跑一次对应单测。",
32    "阶段 4:执行第二批迁移(业务服务层)。",
33    "阶段 5:执行第三批迁移(API 入口层),跑通端到端冒烟。",
34    "阶段 6:清理旧框架残留依赖,输出 MIGRATION_06_report.md",
35]
36
37
38async def main():
39    agent = Agent(
40        model=AnthropicModel(model_id=config.model_id, max_tokens=8192),
41        tools=[file_read, file_edit, shell, grep],
42        system_prompt=(
43            "你负责一次长期迁移工程。\n"
44            "铁律:\n"
45            "1. 每个阶段开始前先读上一阶段的产出文档\n"
46            "2. 每阶段结束必须写一份 markdown 产出文件\n"
47            "3. 任何破坏性操作前先 git commit 一个检查点\n"
48            "4. 连续 3 次工具失败就停下来报告,不要继续瞎试"
49        ),
50        session_manager=session_manager,
51    )
52
53    for i, phase in enumerate(PHASES, 1):
54        print(f"===== {phase[:12]} ... =====")
55        result = await harness.run(agent, prompt=phase, workspace=".", resume=True)
56        print(f"  status={result.status} steps={result.step_count} "
57              f"tokens={result.usage.total_tokens} cost=${result.usage.estimated_cost_usd:.2f}")
58        if result.status != "completed":
59            print("  中断,检查点已保存,修复后重跑本脚本即可续跑")
60            break
61
62
63asyncio.run(main())

三个必须做对的点:

  1. 分阶段,而不是一个大 Prompt。一个大 Prompt 跑到第 5 小时崩了,你不知道该从哪续。分阶段后每个阶段有产出文件,下一个阶段读文件就能接上。
  2. resume=True + 持久化会话。中断后重跑脚本,Harness 从最近检查点续跑,而不是从头。
  3. 阶段性 git commit。这是最后一道保险——Harness 的恢复机制救不了「代码被改成了一坨但逻辑上完成了」的情况。

4.3 场景三:接进 CI,让 PR 自动生成修复建议

任务:CI 里跑 Harness,对失败的测试自动生成补丁(不自动合并)。

yaml
1# .github/workflows/agent-fix.yml
2name: agent-suggest-fix
3on:
4  workflow_run:
5    workflows: ["ci"]
6    types: [completed]
7
8jobs:
9  suggest:
10    if: github.event.workflow_run.conclusion == 'failure'
11    runs-on: ubuntu-latest
12    permissions:
13      contents: read
14      pull-requests: write
15    steps:
16      - uses: actions/checkout@v4
17
18      - name: Run Strands Harness
19        env:
20          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
21          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
22        run: |
23          pip install strands-agents strands-harness strands-agents-tools
24          python -m strands_harness ci \
25            --config .strands/ci.yaml \
26            --failure-log ci-output.txt \
27            --max-cost-usd 3.00 \
28            --out suggested-patch.diff
29
30      - name: Comment patch on PR
31        run: |
32          gh pr comment ${{ github.event.pull_request.number }} \
33            --body-file suggested-patch.diff

CI 专用配置 .strands/ci.yaml:

yaml
1version: 1
2model:
3  provider: anthropic
4  model_id: claude-sonnet-4-5
5  max_tokens: 4096
6
7execution:
8  max_steps: 40
9  max_wall_clock_seconds: 600
10  max_cost_usd: 3.00
11  mode: read-only-until-approved   # 关键:不允许直接写文件,只产出 diff
12
13tools:
14  allow: [file_read, grep, shell]
15  shell_allowlist:                 # CI 里必须白名单化 shell
16    - "pytest"
17    - "npm test"
18    - "git diff"
19    - "git log"
20  denylist_paths: [".git/**", "**/.env*"]
21
22output:
23  format: unified-diff
24  forbid_paths: [".github/**", "ci/", "**/*.lock"]

CI 场景的三条红线:

  1. mode: read-only-until-approved:Agent 只能产出 diff,不能直接改仓库。自动合并 Agent 补丁是 2026 年最大的供应链风险来源之一。
  2. shell_allowlist:CI 里绝不能给 Agent 无限制 shell。只放行测试与只读 git 命令。
  3. forbid_paths:CI 配置、锁文件、工作流文件一律禁止 Agent 碰。改了这些等于让 Agent 修改自己的运行环境。

五、高级配置:把省 Token 的三个机制调明白

5.1 机制一:工具输出截断(约 1500 Token)

原理:工具返回值超过阈值时,Harness 不把它塞进上下文,而是:

  1. 完整内容落盘到 artifact 目录
  2. 上下文里只保留头部 N 个 Token + 文件路径 + 行数统计
  3. Agent 需要更多时,用 artifact_read 工具按行区间再取

配置:

yaml
1context:
2  tool_output_max_tokens: 1500
3  artifact:
4    dir: .strands/artifacts
5    keep_head_tokens: 600
6    keep_tail_tokens: 200
7    ttl_hours: 72

怎么调:

任务类型建议值理由
代码重构 / 批量改名800–1200命中和片段都短,压狠点
日志分析 / 报错排查4000–6000需要看到上下文邻近行,压太狠会丢关键信息
文档生成 / 长文写作2000–3000中等
数据分析(CSV/JSON)1000 + schema 提示不要直接塞数据,让 Agent 写代码去统计

最容易踩的坑:日志排查场景用了默认的 1500,Agent 只看得到错误行的头尾,中间的关键堆栈被截掉,于是它开始瞎猜。症状是 Agent 反复读同一个日志文件。解法:把日志类工具单独配一个大阈值,而不是全局调大。

yaml
1context:
2  tool_output_max_tokens: 1500
3  per_tool_overrides:
4    log_read: 6000
5    stack_trace: 8000

5.2 机制二:上下文自动摘要(85% 触发)

原理:上下文占用达到 compaction_threshold 时,触发一次结构化压缩:

  1. 保留:系统提示、任务目标、最近 N 轮完整对话
  2. 压缩:中间历史 → 结构化摘要(已完成步骤 / 关键发现 / 待办 / 已试错的死路)
  3. 保留:工具产物的文件引用(不丢内容,只是移出上下文)

为什么结构化摘要比「丢最早的轮次」强:丢轮次会丢失「我们试过 A,失败原因是 B」这类负面知识,Agent 会重蹈覆辙。结构化摘要会显式保留死路清单。

yaml
1context:
2  compaction_threshold: 0.85
3  compaction_target: 0.55
4  compaction:
5    keep_last_turns: 4
6    summary_model: claude-haiku-4-5        # 用便宜模型做摘要
7    summary_max_tokens: 1500
8    preserve_sections:
9      - system_prompt
10      - task_objective
11      - dead_ends
12      - file_artifacts

用便宜模型做摘要是这里最大的杠杆:摘要任务本身不需要强模型,换成 Haiku 级别能把压缩开销降一个数量级。

5.3 机制三:溢出恢复(recovery_on_overflow)

原理:触发 context_length_exceeded 时:

  1. 捕获错误(不崩溃)
  2. 强制触发一次压缩到 compaction_target
  3. 如果仍放不下,把当前步的超大工具输出替换为 artifact 引用重试
  4. 重试成功则续跑,失败 N 次后才判定任务失败
yaml
1context:
2  recovery_on_overflow: true
3  recovery:
4    max_attempts: 3
5    strategy: compact-then-evict-then-retry
6    on_failure: checkpoint-and-report

关掉它会发生什么:一次溢出 = 整轮重跑 = 前面的钱全白花。长任务必开。

5.4 预算与熔断(防止半夜烧穿信用卡)

yaml
1execution:
2  max_steps: 120
3  max_wall_clock_seconds: 1800
4  max_cost_usd: 8.00
5  per_tool_budget_usd: 2.00
6  max_consecutive_tool_failures: 5
7  loop_detection:
8    enabled: true
9    window: 6
10    similarity_threshold: 0.92
11  on_budget_exceeded: checkpoint-and-abort

四项预算要一起设:

预算防的是什么
max_steps步数失控的推理循环
max_wall_clock_seconds卡在某个慢工具上不动
max_cost_usd总体烧穿
per_tool_budget_usd单个工具(通常是 shell 或 http)被反复调用

只设总预算不设单工具预算,常见后果是:Agent 在某个失败的网络请求上重试 200 次,把 8 美元全花在同一个错误上,然后整体 abort,你既没结果也没钱。

5.5 可观测性:知道钱花在哪

yaml
1telemetry:
2  otel_endpoint: http://localhost:4318
3  trace_dir: .strands/traces
4  jsonl: true
5  redact_patterns:
6    - "sk-ant-[A-Za-z0-9_-]+"
7    - "sk-[A-Za-z0-9]{20,}"
8    - "AKIA[0-9A-Z]{16}"
9    - "ghp_[A-Za-z0-9]{36}"
10  metrics:
11    - tokens_by_tool
12    - cost_by_step
13    - compaction_events
14    - loop_detections

一次任务跑完,看按工具的 Token 分布:

bash
1python -m strands_harness report --trace .strands/traces/tsk_xxx.jsonl --by tool
text
1tool                calls    tokens      %      cost
2file_read             47     612,400   38.2%   $1.84
3shell                 31     401,200   25.0%   $1.20
4file_edit             12     186,000   11.6%   $0.56
5grep                  23     142,800    8.9%   $0.43
6context_compaction     4      98,000    6.1%   $0.29
7------------------------------------------------------
8TOTAL                117   1,603,700  100.0%   $4.81

看到这张表你就知道该优化什么了。如果 file_read 占 38%,说明该让 Agent 用 grep 先定位再读;如果 context_compaction 占 6% 以上,说明压缩太频繁,该调大 compaction_threshold 或减少每步的上下文携带。

5.6 自定义 Hook:在关键节点插手

python
1from strands_harness import Harness, HookContext
2
3
4@harness.hook("before_tool_call")
5async def guard_shell(ctx: HookContext):
6    """禁止 Agent 在工作区外执行破坏性命令。"""
7    if ctx.tool_name != "shell":
8        return ctx.proceed()
9
10    cmd = ctx.tool_input.get("command", "")
11    banned = ["rm -rf /", "git push --force", "curl | sh", "chmod 777"]
12    for b in banned:
13        if b in cmd:
14            return ctx.block(reason=f"命中禁令: {b}")
15
16    if cmd.strip().startswith("rm ") and ".." in cmd:
17        return ctx.block(reason="禁止在工作区外删除文件")
18
19    return ctx.proceed()
20
21
22@harness.hook("after_step")
23async def cost_guard(ctx: HookContext):
24    if ctx.cumulative_cost_usd > 5.0:
25        ctx.log.warning("成本已过 5 美元,当前步骤 %s", ctx.step_index)
26    return ctx.proceed()

Hook 是关键节点上唯一能「硬拦」的地方。**Prompt 里写「不要执行危险命令」是软约束,会被模型偶尔忽略;Hook 是代码级硬约束,绕不过去。**危险操作一律走 Hook,不要只写在提示词里。


5.7 会话持久化与并发

单任务跑通之后,下一步一定是「一次跑很多个」。这里有两件事必须先搞对。

会话存储后端

python
1from strands.session.file_session_manager import FileSessionManager
2from strands.session.s3_session_manager import S3SessionManager
3
4# 本地:适合单机、调试、CI
5local = FileSessionManager(session_dir=".strands/sessions")
6
7# S3 / 兼容 S3 的对象存储:适合多机、团队共享、需要长期留存
8remote = S3SessionManager(
9    session_id="batch-2026-09-22",
10    bucket="my-strands-sessions",
11    prefix="tasks/",
12)
yaml
1session:
2  backend: s3                # file | s3 | redis | postgres
3  bucket: my-strands-sessions
4  prefix: tasks/
5  ttl_days: 30
6  checkpoint:
7    every_n_steps: 25
8    include: [messages, artifacts_index, tool_state, cost_so_far]

checkpoint.include 里不要放完整工具输出。那些已经在 artifact 里了,重复存一份会让会话体积涨十倍。只存索引。

并发:每个任务独立 workspace

python
1import asyncio
2from pathlib import Path
3
4async def run_batch(tasks: list[str], concurrency: int = 4):
5    sem = asyncio.Semaphore(concurrency)
6
7    async def one(idx: int, prompt: str):
8        async with sem:
9            ws = Path(f".strands/workspaces/t{idx:03d}")
10            ws.mkdir(parents=True, exist_ok=True)
11            agent = Agent(
12                model=AnthropicModel(model_id="claude-sonnet-4-5", max_tokens=8192),
13                tools=[file_read, file_edit, shell, grep],
14            )
15            return await harness.run(agent, prompt=prompt, workspace=str(ws))
16
17    return await asyncio.gather(*[one(i, p) for i, p in enumerate(tasks)])
18
19
20results = asyncio.run(run_batch([
21    "任务 A 描述",
22    "任务 B 描述",
23    "任务 C 描述",
24], concurrency=4))

并发时最容易犯的错:多个任务共用一个 workspace 目录,互相覆盖对方的中间文件。症状是「单跑没问题,并发就乱」——每个任务一个独立目录,这条没有例外。

并发度怎么定:

约束建议并发度
本地单容器,内存 < 4G2–3
本地,内存 8G+4–6
云端容器,每容器 2 CPU每容器 2
有 API 速率限制按限流配额 ÷ 单任务平均 RPM

别只看本机资源。并发上去之后先撞的通常是模型 API 的速率限制。先跑小批量测出实际 RPM,再定并发度。

5.8 结构化输出:让 Agent 的输出可被程序消费

Agent 的输出如果只是给人看的,你永远没法自动化。Harness 支持 grammar 约束的结构化输出:

python
1from pydantic import BaseModel, Field
2from typing import Literal
3
4
5class RefactorPlan(BaseModel):
6    """重构计划的结构化输出。"""
7    summary: str = Field(description="一句话说明这次重构要做什么")
8    affected_files: list[str] = Field(description="将被改动的文件路径清单")
9    risk_level: Literal["low", "medium", "high"]
10    risky_points: list[str] = Field(description="具体风险点,每条给文件路径与原因")
11    verification_commands: list[str] = Field(description="验证重构是否成功的命令")
12    blockers: list[str] = Field(default_factory=list, description="需要人类确认的问题")
13
14
15result = await harness.run(
16    agent,
17    prompt="分析这个仓库的重构需求,输出重构计划",
18    workspace=".",
19    output_schema=RefactorPlan,
20)
21
22plan = result.structured_output      # 已校验过的 Pydantic 对象
23if plan.blockers:
24    print("需要人工确认:", plan.blockers)
25else:
26    print("风险等级:", plan.risk_level)
27    for cmd in plan.verification_commands:
28        print("  -", cmd)

为什么值得做:

对比项自由文本输出结构化输出
下游能否自动消费需要再解析一次(脆弱)直接用
字段缺失静默发生,运行到一半才炸校验阶段就报错
幻觉字段无法检测schema 不认识的字段直接拒
与 CI 集成难天然适配

代价:结构化输出会略微降低模型的表达自由度,且首次生成可能多消耗一些 token。判断标准很简单——输出要给程序用就结构化,给人看就自由文本。

5.9 工具集组织:分层与渐进披露

工具不是越多越好。工具定义本身占上下文,20 个工具的详细 schema 轻松吃掉 8–10K token,且每次请求都要带上。

分层工具集

yaml
1tools:
2  # 核心层:始终加载
3  core:
4    - file_read
5    - file_write
6    - file_edit
7    - grep
8    - shell
9
10  # 扩展层:按需加载(Agent 显式请求时才注入 schema)
11  on_demand:
12    - http_request
13    - database_query
14    - docker_exec
15    - git_operations
16    - mcp_bridge
17
18  # 危险层:需要人类批准才能用
19  gated:
20    - npm_publish
21    - git_push
22    - deploy

渐进披露的效果:核心 5 个工具约 2.5K token,全部 15 个约 9K token。分层的版本在长任务里能省下可观的固定开销。

gated 工具与批准流

python
1@harness.hook("before_tool_call")
2async def require_approval(ctx: HookContext):
3    if ctx.tool_name in ("npm_publish", "git_push", "deploy"):
4        approved = await ctx.request_human_approval(
5            reason=f"Agent 请求执行高风险操作: {ctx.tool_name}",
6            detail=ctx.tool_input,
7            timeout_seconds=300,
8        )
9        return ctx.proceed() if approved else ctx.block(reason="人类拒绝")
10    return ctx.proceed()

危险工具一定要进 gated 层并用 Hook 拦。把它们和普通工具混在一起,等于把发布权限交给了模型的判断力。

5.10 与 MCP 集成

Harness 可以直接消费 MCP 服务器提供的工具:

python
1from strands.tools.mcp import MCPClient
2from mcp import StdioServerParameters
3
4beacon = MCPClient(
5    StdioServerParameters(
6        command="npx",
7        args=["-y", "@asymptote-labs/beacon-mcp"],
8        env={"BEACON_HOME": "/Users/you/.beacon"},
9    )
10)
11
12with beacon:
13    mcp_tools = beacon.list_tools_sync()
14    agent = Agent(
15        model=AnthropicModel(model_id="claude-sonnet-4-5", max_tokens=8192),
16        tools=[file_read, file_edit, shell, grep, *mcp_tools],
17    )
18    result = await harness.run(agent, prompt="...", workspace=".")

YAML 配置方式:

yaml
1mcp:
2  servers:
3    beacon:
4      transport: stdio
5      command: npx
6      args: ["-y", "@asymptote-labs/beacon-mcp"]
7      env:
8        BEACON_HOME: /Users/you/.beacon
9      tool_filter:
10        include: ["beacon_search_memory", "beacon_dead_ends"]
11    context7:
12      transport: stdio
13      command: npx
14      args: ["-y", "@upstash/context7-mcp"]
15  limits:
16    max_servers: 4
17    max_tools_total: 20
18    call_timeout_seconds: 30

tool_filter.include 很重要。一个 MCP 服务器可能暴露十几个工具,你通常只需要其中两三个。全量加载会白吃上下文。

max_tools_total: 20 建议别超过。超过之后工具选择准确率会明显下降——模型开始选错工具,反而更慢更贵。

5.11 成本基准:三类任务的实测对比

同一模型、同一仓库,裸 SDK 与 Harness 的对照(每类任务跑 3 次取平均):

任务类型方案步数总 Token成本结果
批量重构(200 文件)裸 SDK1634,182,000$12.55完成(1 次溢出重跑)
Harness 默认1583,041,000$9.12完成
Harness + 激进压缩1492,466,000$7.40完成
日志排查(需长输出)裸 SDK22890,000$2.67完成
Harness 默认 1500311,142,000$3.43反复重读,变差
Harness + 日志工具 600019764,000$2.29完成,更优
短任务(单文件改动)裸 SDK648,000$0.14完成
Harness 默认652,000$0.16完成(略贵)

从这张表能读出三条结论:

  1. 重复上下文多的任务收益最大(批量重构 -41%)
  2. 长输出任务必须调 per_tool_overrides,用默认值反而更贵更差
  3. 短任务别上 Harness,多出来的摘要与 trace 开销超过收益

这就是「28% 平均降幅」的真相:它是按任务分布加权算出来的。你的任务分布不同,实际收益可能是 -15%(变差)也可能是 -45%。先测自己的任务,再决定要不要上。

5.12 提示词分层与上下文预算

Harness 省的是「执行层」的 Token,但上下文里装什么,仍然是你的责任。把提示词拆成三层来管理:

text
1┌─ L1 系统提示(常驻,每轮都带)───────────┐  目标 < 800 token
2│  角色、铁律、输出格式、全局禁区            │
3└────────────────────────────────────────┘
4┌─ L2 项目规范(常驻,来自 AGENTS.md)──────┐  目标 < 1500 token
5│  技术栈、编码规范、命令清单、关键禁区      │
6└────────────────────────────────────────┘
7┌─ L3 任务上下文(按需,动态注入)──────────┐  按需,用完即弃
8│  当前任务目标、相关文件内容、工具结果      │
9└────────────────────────────────────────┘

L1 系统提示的写法

反例(太长、太虚):

text
1你是一个经验丰富、专业、严谨、乐于助人的高级软件工程师。
2你应该写出高质量、可维护、高性能、安全的代码。
3你应该遵循最佳实践,注意代码质量,考虑边界情况,
4遵循设计模式,写好注释,写出优雅的代码...

这段话约 120 token,提供的可执行信息接近 0。每轮都带上,跑 100 步就是白白消耗 12K token。

正例(短、可执行):

text
1你是代码工程 Agent。
2
3规则:
41. 先读后改,禁止凭猜测写文件
52. 修改前确认工作区干净(git status --porcelain 为空)
63. 每次修改后跑相关测试
74. 不确定时停止并标注 [BLOCKER],不要硬猜
8
9禁止:
10- 不修改 .github/ 与锁文件
11- 不执行 rm -rf / git push --force
12- 不引入新依赖
13
14输出:每步先说要做什么,再做,最后贴验证输出。

约 130 token,但每一条都是可判定的。

L2 项目规范的边界

项目规范文件(AGENTS.md)每次会话都会被注入。实测一个 900 行的规范文件,每轮多花约 12K token——在 100 步的任务里是 1.2M token。

控制原则:

内容类型放规范文件放 docs/ 用链接指过去
技术栈与版本✅
构建/测试命令✅
编码风格要点✅(≤ 20 条)
关键禁区(带原因)✅
详细架构说明✅
完整 API 文档✅
历史决策记录✅

「不确定的信息用链接,确定的规则用文字」。 Agent 需要时自己去读,不需要时不占上下文。

L3 上下文预算的分配

yaml
1context:
2  budget:
3    system_prompt: 800
4    project_spec: 1500
5    task_context: 20000
6    tool_schema: 4000
7    history: dynamic

给每层设上限,超了就报警而不是静默吞掉。很多「Agent 后半段变笨」的现象,本质是上下文被某一层悄悄吃满了。

5.13 五个常见反模式

反模式表现后果正解
系统提示写成作文300 行价值观描述每轮白烧 token,且无可执行信息压到 20 条以内,每条可判定
工具全量加载20 个工具 schema 常驻固定开销 9K token/轮分层加载 + tool_filter
日志类工具用默认截断堆栈被截掉Agent 反复重读同一文件per_tool_overrides 调大
只设总预算单个失败工具重试 200 次钱花在同一个错误上四项预算一起设
trace 不脱敏密钥进了 JSONL合规事故redact_patterns + 定期自查

六、部署:本地与五朵云

6.1 本地 / 自有服务器(国内推荐)

yaml
1runtime:
2  type: local
3  workspace_root: /srv/workspaces
4  sandbox:
5    enabled: true
6    backend: container          # container | firejail | none
7    image: strands/sandbox:py312
8    network: none               # 默认断网,需要联网的工具显式开白名单
9    memory_limit: 2g
10    cpu_limit: 2

network: none 是默认正确的选择。Agent 的绝大多数编码任务不需要联网,断网能一次性掐掉数据外传这条路径。需要拉依赖时,用白名单放行特定域名:

yaml
1sandbox:
2  network: allowlist
3  network_allowlist:
4    - pypi.org
5    - registry.npmjs.org

6.2 AWS

yaml
1runtime:
2  type: aws
3  target: lambda                # lambda | fargate | bedrock-agentcore
4  region: us-west-2
5  lambda:
6    memory_mb: 2048
7    timeout_seconds: 900
8    ephemeral_storage_mb: 2048
9  session:
10    backend: s3
11    bucket: my-strands-sessions
12  secrets:
13    provider: secrets-manager
14    key_arn: arn:aws:secretsmanager:...

Fargate 更适合长任务(Lambda 有 15 分钟硬上限):

yaml
1runtime:
2  type: aws
3  target: fargate
4  fargate:
5    cpu: 2048
6    memory: 4096
7    task_timeout_hours: 6

6.3 GCP Cloud Run

yaml
1runtime:
2  type: gcp
3  target: cloud-run
4  region: asia-east1
5  cloud_run:
6    cpu: 2
7    memory: 4Gi
8    timeout_seconds: 3600
9    min_instances: 0
10  model:
11    provider: vertex
12    model_id: gemini-3-pro

6.4 Azure Container Apps

yaml
1runtime:
2  type: azure
3  target: container-apps
4  container_apps:
5    cpu: 2.0
6    memory: 4.0Gi
7    min_replicas: 0
8    max_replicas: 10
9  model:
10    provider: azure-openai
11    deployment: gpt-5-mini

6.5 Cloudflare Workers

yaml
1runtime:
2  type: cloudflare
3  target: workers
4  workers:
5    compatibility_date: "2026-09-01"
6  limits:
7    cpu_ms: 30000               # Workers 有 CPU 时间上限
8  model:
9    provider: workers-ai
10    model_id: "@cf/meta/llama-4"

注意:Workers 有 CPU 时间与内存硬限制,只适合短任务(步数 < 30)。别拿长迁移任务往 Workers 上放。

6.6 Modal

yaml
1runtime:
2  type: modal
3  modal:
4    gpu: null                   # 自托管模型时用 "A10G"
5    memory_mb: 8192
6    timeout_seconds: 7200
7    volumes:
8      - /workspace

Modal 适合需要 GPU 跑自托管模型、或任务时长不可控的场景。

6.7 国内模型接入(openai-compatible)

yaml
1model:
2  provider: openai-compatible
3  base_url: https://your-endpoint.example.com/v1
4  api_key_env: MODEL_API_KEY
5  model_id: your-model-name
6  max_tokens: 8192
7  pricing:                      # 手动填单价,否则成本估算全是 0
8    input_per_mtok: 2.0
9    output_per_mtok: 6.0

pricing 必须填。不填的话 Harness 的成本统计和预算熔断全部失效——它会认为一切免费,然后一路跑到 max_steps。


七、与同类方案的选型对比

方案形态优势劣势适合
Strands Harness可嵌入库(Py/TS)双语言、多云、上下文策略透明可调、Apache 2.0需要自己写代码集成自建 Agent 服务 / CI / 批量任务
Claude Code CLI终端交互式开箱即用、体验成熟难以程序化嵌入、不便于批量日常交互式编码
Codex CLI终端交互式与 OpenAI 生态紧耦合同上同上
OpenAI Agents API托管 API免运维、有沙箱控制权与数据在厂商侧不想自建基础设施的团队
LangGraph图编排库状态机表达力强学习曲线陡、上下文策略要自己写复杂确定性流程
自写 while 循环—完全可控五个坑全要自己填一遍学习用途

选型一句话:要「Agent 跑在自己的基础设施上、且能精细控制成本」,选 Harness;要「人在终端前写代码」,选 CLI;要「一点都不想运维」,选托管 API。


八、故障排查表

#症状根因排查命令解法
1context_length_exceeded 直接失败recovery_on_overflow 未开grep context_overflow traces/*.jsonl设为 true,配 recovery.max_attempts: 3
2Agent 反复读同一个文件工具输出被截断,看不到想要的内容grep tool_output_truncated traces/*.jsonl | tail对日志类工具配 per_tool_overrides 调大阈值
3任务跑满 max_steps 却没结果步数上限过小或陷入隐含循环grep loop_detected traces/*.jsonl开 loop_detection;或拆分任务
4成本估算永远显示 $0.00自定义 provider 未填 pricing检查配置里 model.pricing填 input_per_mtok / output_per_mtok
5预算没生效,跑超了只设了 max_steps,没设 max_cost_usd看配置 execution 段四项预算一起设,见 5.4
6Docker 起不来,端口占用8080 被占ss -lntp | grep 8080-p 8081:8080 换端口
7model provider unreachableKey 没传进容器docker exec strands env | grep API_KEY-e ANTHROPIC_API_KEY=... 显式传
8trace 里出现明文密钥脱敏未配grep -rIl "$KEY" logs/配 telemetry.redact_patterns
9Agent 改了 .env 文件denylist 没排 .env检查 tools.denylist_paths加 **/.env*
10摘要后 Agent 忘了关键约定摘要把系统提示压掉了检查 compaction.preserve_sections把 system_prompt 加入保留段
11压缩极其频繁(每 3 步一次)compaction_threshold 太低或单步上下文太大grep context_compaction traces/*.jsonl | wc -l阈值调到 0.88;减少工具返回体积
12摘要本身很贵用了旗舰模型做摘要看 compaction.summary_model换成 Haiku / Flash 级模型
13沙箱里装不了依赖network: none检查 sandbox.network改 allowlist 并加域名
14CI 里 Agent 改了工作流文件没配 output.forbid_paths看 .strands/ci.yaml加 .github/**
15长任务中断后从头跑没开 resume 或没配 session_manager检查 .strands/sessions/FileSessionManager + resume=True
16Terminal-Bench 类任务得分低shell 工具被过度限制看 tools.shell_allowlist放通必要命令,但保持白名单制
17Python 与 TS 行为不一致两版 SDK 版本号不同步pip show strands-harness / npm ls锁同一 major 版本
18并发跑多任务时互相干扰共用同一 workspace检查 workspace_root每任务独立 workspace 目录
19artifact 目录撑爆磁盘ttl_hours 未设或过大du -sh .strands/artifacts设 72 小时 TTL 并加定时清理
20并发跑时结果互相覆盖多任务共用 workspace检查 workspace 路径每任务独立目录,见 5.7
21结构化输出校验失败率高schema 字段描述太模糊看 result.validation_errors给每个 Field 补 description;减少嵌套层级
22MCP 工具选错工具总数超过 20beacon_stats / 看工具 schema 数用 tool_filter.include 裁剪到 15 个以内
23长任务后半段明显变笨上下文被某一层吃满看 context.budget 各层占用给每层设上限并告警,见 5.12
24危险命令真的被执行了只在 Prompt 里写了禁令grep '"blocked"' traces/*.jsonl用 Hook 硬拦,见 5.6

九、一条最重要的实践原则

Strands Harness 把执行层的脏活标准化了,这是好事。但它不会替你定义「什么叫做完了」。

跑任何任务前,先把这四件事写成机器可验证的东西:

  1. 验收标准:跑什么命令、通过什么阈值算完成
  2. 禁区:哪些文件、哪些命令绝对不能碰(走 Hook 硬拦,不只写进 Prompt)
  3. 预算:步数、时间、金额三个上限
  4. 中断点:多久落一次检查点、中断后从哪续

有了这四件事,Harness 才能安全地跑无人值守任务。没有这四件事,它只会更快地把事情做错。


十、下一步

  • 把项目规范写进 AGENTS.md,让 Harness 与 CLI 工具共享同一套约束(见本站 AGENTS.md 统一配置实战)
  • 接 MCP 工具扩展能力(见本站 MCP 系列)
  • 用 Beacon 之类的跨 Harness 记忆层,把这次任务里学到的经验沉淀给下一次(见本站 Beacon MCP)

常见问题(正文补充)

Q:默认值够用吗? 够用,但三处建议立刻改:denylist_paths 加 .env*;telemetry.redact_patterns 配上;max_cost_usd 设一个你真的能接受的数字。

Q:能不能和 Claude Code 共存? 能,而且推荐共存。日常交互用 CLI,批量与自动化用 Harness,两者共享 AGENTS.md 与工具定义。

Q:28% 是稳定收益吗? 取决于任务形态。重复上下文多、工具输出大的任务收益明显(实测 25%–35%);单轮短任务收益接近 0,甚至因为多了摘要步骤而略微变贵。别指望它治所有病。

常见问题

QStrands Harness 和 Strands Agents SDK 到底什么关系?

SDK 负责「一个 Agent 怎么思考和调工具」,Harness 负责「一次任务怎么跑完」。SDK 里你写 Agent(model=..., tools=[...]) 然后 agent('做件事'),剩下的循环、错误重试、上下文管理归 Harness。换句话说:SDK 是引擎,Harness 是车身加底盘。只用 SDK 的话,循环、截断、摘要、恢复、并发、可观测性全部要你自己写;上了 Harness 之后这些是默认行为,只需要在配置里调参数。本文第 2 节给了两者的职责对照表。

Q那 28% 的 Token 节省到底来自哪里?会不会是牺牲质量换的?

主要来自三个确定性机制,不是靠「让模型少说话」:工具输出超过约 1500 Token 就截断并落盘为引用;上下文占用到 85% 触发结构化摘要而非暴力裁剪;上下文溢出后走恢复流程而不是整轮重跑。官方口径是「准确率相近时」的成本下降,Terminal-Bench 2.1 上得分还高 7.9 点——说明截断策略反而降低了噪音干扰。但要注意:这三个机制默认开启,如果你的任务依赖超长工具输出(比如完整日志分析),需要手动调大截断阈值,见第 5 节。

Q我已经在用 Claude Code / Codex CLI 了,还有必要引入 Strands Harness 吗?

分场景。交互式日常编码,现成的 CLI 体验更好,别换。但如果你要做的是「把 Agent 跑在自己的基础设施上」——批量任务、CI 流水线、需要审计日志、需要自托管模型、需要跨云部署——Harness 这类可嵌入的框架才是正确选择,因为 CLI 工具的设计前提是「人在终端前」。一个实用的折中:日常用 CLI,批量和自动化部分用 Harness,两者共享同一套工具定义与项目规范文件(AGENTS.md)。

Q它能在国内网络环境跑吗?会不会强绑 AWS?

不强绑。Harness 本身是 Apache 2.0 的开源库,本地运行不依赖任何 AWS 服务;模型层通过 provider 抽象接入,Bedrock、Anthropic、OpenAI、Ollama、LiteLLM、以及兼容 OpenAI 协议的国内模型都能配。云端部署适配器里确实有 AWS Lambda / Fargate / Bedrock AgentCore,但同时也有 GCP Cloud Run、Azure Container Apps、Cloudflare Workers、Modal。国内使用建议本地或自有服务器部署,模型走兼容 OpenAI 协议的国内 endpoint,见第 6 节的配置片段。

阿里云推广

读完想动手?新用户首单 8 折上云

服务器 + 大模型 API + 对象存储,新用户首购享 20% 补贴

首单 8 折云服务器大模型 API对象存储

新用户首购享 20% 补贴(8 折)· 本次推广支持本站持续运营

腾讯云推广

腾讯智能体开发平台 ADP

新客首月专属价,最高直降 880 元,构建/分发/治理企业级 Agent

智能体Agent首月直降 880一站式

腾讯云新用户专享 · 本次推广支持本站持续运营

订阅每日 AI 日报

每天早上 8:00(GMT+8)把当天 AI 行业要闻投递到你的邮箱,随时一键退订。

每天早上 8:00(GMT+8)投递当天日报;若当天日报未生成则不发送,也不会补发往期。

更多订阅方式(RSS / 微信推送)仅发送日报,不做任何其他用途

相关推荐

查看更多 →
教程编辑器接入

通义千问 Qwen3 接入 VS Code 指南:双插件分工与选型

Qwen3 是阿里云百炼上当前最值得接进编辑器的国产模型系列:中文需求转代码、中文注释生成、既有风格代码改写三项能力都在第一梯队,价格只有同级海外模型的零头。本篇解决三个 VS Code 场景下的真实问题:一是 VS Code 官方 Copilot 的补全通道绑定 GitHub 账号,换不了模型,所以接入 Qwen3 必须靠 Continue(对话 + 行内编辑)和 Cline(Agent)两个插件分工,本篇给出两边的准确填法;二是百炼 OpenAI 兼容端点的 Base URL 必须带 /v1 这一层,90% 的配不通都栽在这里;三是模型档位怎么选——qwen3-max、qwen-plus、qwen3-coder-plus 各管什么任务,选错档位要么贵一倍要么答非所问。全文给出双插件配置步骤、四档模型选型矩阵、成本估算对照表、18 行故障排查表,以及三条避坑结论。

2026-10-21
#通义千问#Qwen3
教程AI 助手接入

DeepSeek V4.1 Flash 接入 WorkBuddy 完整指南与降本实测

DeepSeek V4.1 Flash 是 552B 总参数的非对称 MoE 模型:输入激活 8B、输出激活 16B,单Token KV 缓存从 3514 字节压到 890 字节(SSD 占用降 88%),且已被官方选为 WorkBuddy / CodeBuddy 的推理底座。本文给出把它接进腾讯桌面端 AI 助手 WorkBuddy 的完整两条路径:零代码的「模型配置」面板交互接入(5 分钟,含自定义供应商完整 6 项填写说明)与「配置文件手动接入」(JSON + 环境变量 + 多档位模型定义)。含 V4.1 Flash 在长文档摘要 / 批量信息抽取 / 日常问答三个场景的实测数据、峰谷定价下的成本对比(闲时比高峰省 50%)、与 Qwen3-Max / Kimi K3 / Claude Opus 5.5 的横向选型表、thinking 模式 reasoning_content 字段的兼容处理、WorkBuddy Agent 模式下的 KV 缓存命中率优化七条,以及 18 行故障排查表(覆盖 401 / 404 / 429 / reasoning_content 解析失败 / 模型名不存在等真实报错)。

2026-10-13
#DeepSeek#V4.1 Flash
教程编辑器接入

通义千问 Qwen3-Max 接入 Cursor 完整指南

Qwen3-Max 是阿里云百炼平台上通义千问系列的旗舰文本模型,中文代码注释理解、中文需求转代码、长上下文仓库问答三项在国产模型里属于第一梯队,价格只有同级海外模型的零头。本篇解决一个绝大多数教程都没讲清楚的问题:Cursor 里的「模型」根本不是一个开关,而是三套彼此独立的通道——Chat/Agent 走 Custom API、Cmd+K 走同一个 Custom API 但行为不同、Tab 补全(Copilot++)完全不走 Custom API。很多人填完 Base URL 发现「补全还是英文、还是 Cursor 自己的模型」,就是因为没搞清这三者的边界。全文给出百炼 OpenAI 兼容端点的准确填法、四个模型档位的选型矩阵、Cursor Rules 针对国产模型的写法、Context 与成本实测数据、四场景 token 对照表,以及 17 行故障排查表。

2026-10-12
#通义千问#Qwen3-Max
教程IDE工具接入

DeepSeek V4.1 Flash 接入 Cursor 指南:BYOK 与 Rules 配置

Cursor 的 Pro 订阅每月只给固定配额的高速请求,超出后要么排队要么降速,而绝大多数日常编码请求并不需要最强的那档模型。本教程给出把 DeepSeek V4.1 Flash 接进 Cursor 的完整两条路径:成本最低的「BYOK 自定义 OpenAI 兼容模型」(5 分钟完成,覆盖 Tab 补全、Cmd-K 内联编辑、Agent 三种能力)与最稳的「自建 OpenAI 兼容代理 + Docker 一键部署 + 源码手动配置」(解决鉴权头不一致、Function Calling 降级、429 限流重试三个硬伤)。含 V4.1 Flash 在 Cursor Agent 多文件重构场景下的实测数据(62 个文件重命名 8 分 41 秒、单文件成本约 ¥0.011)、与 Claude Opus 5.5 / GPT-6 的横向对比、Cursor Rules 八条约束模板、键位映射表,以及 21 行故障排查表。

2026-10-10
#DeepSeek#V4.1 Flash

好物推荐 · 广告合作