第 10 章:组装与发布 — 从模块到产品

六大模块各自就绪——现在把它们焊在一起

📝 本章目标

读完本章,你将:

  1. 用四个 Prompt 让 AI 帮你把前九章的模块连接配置启动打包成一个完整的产品
  2. 理解配置优先级的分层设计——CLI、环境变量、配置文件、默认值,谁说了算
  3. 掌握 Agent 的启动顺序为什么重要——初始化的先后决定了系统能不能跑
  4. 学会为 AI Agent 设计测试策略,用打包工具把它发布出去

你造过模型车吗?

发动机装好了,变速箱调好了,轮子轮轴都打磨完毕,方向盘和座椅也到位了。每个零件单独测试都没问题——发动机能转、变速箱能换挡、轮子能滚。但现在把它们全摊在桌上,你面对的不是一辆车,而是一堆很好的零件

从零件到整车,你还需要做四件事:把零件起来(发动机连变速箱,变速箱连传动轴,传动轴连车轮),调整每个零件的参数让它们配合(齿轮比、轮距、悬挂高度),确定启动顺序(先通电、再点火、再挂挡),最后装上外壳变成一辆别人能开的车。

我们的 harness 现在就是这堆零件。查询引擎、工具系统、权限系统、Agent 编排、记忆系统、钩子与技能、MCP 集成、终端界面——九章下来,每个模块都能独立工作。但它们还没有变成一个你能递给别人说”装上就能用”的产品。

这一章,我们完成最后四步:连接、配置、启动、打包。做完这一步,你手里就不再是一堆零件,而是一辆能开上路的车。

先动手造出来,再回头理解。

动手:用四个 Prompt 完成最终组装

确保你跟着前九章做了项目——查询引擎、工具系统、权限系统、Agent 编排、记忆系统、钩子与技能、MCP 集成、终端界面全部就绪。如果没有,去 GitHub 仓库 git checkout ch09-terminal 获取起点。

打开 Claude Code,确认你在项目根目录,然后跟着走。

Prompt 1:把所有模块连起来

前九章的模块现在是各自独立的——查询引擎不知道要先加载记忆,工具系统不知道要先注册 MCP 工具,权限系统不知道钩子什么时候该跑。第一步是把它们串起来,让数据能在模块间流动。

复制下面这段话,粘贴到 Claude Code 里:

帮我写一个总的组装文件,把所有模块连起来:

1. 查询引擎调用工具时,要先过权限系统检查
2. 工具列表要包含内置工具和 MCP 外部工具
3. 会话开始时要加载记忆,结束时要保存记忆
4. 钩子要在对应的时机自动触发
5. 终端渲染要接管所有输出
6. Agent 编排要能在需要时启动子 Agent

最终只暴露一个入口函数,
调用它就能启动整个系统。

等 AI 跑完,它会创建一个组装模块——通常叫 app.pyharness.py——把所有模块的初始化和连接逻辑集中在一起。试一下:

$ python -c "from harness.app import create_app; print(create_app)"
<function create_app at 0x...>

$ harness
[init] Loading config...
[init] Registering 8 built-in tools
[init] Connecting 2 MCP servers... OK (8 external tools)
[init] Loading permissions rules
[init] Loading hooks (3 active)
[init] Loading memory (5 entries)
[init] Terminal renderer ready

Harness v0.1.0 — AI Agent Runtime
You > 你好
Assistant > 你好!有什么可以帮你的?

所有模块连上了,启动日志能看到每个模块的初始化过程。但现在所有参数都是硬编码的——模型名、API key、超时时间都写死在代码里。下一步让它们可配置。

Prompt 2:统一配置管理

帮我做一个统一的配置系统:

1. 支持配置文件——在项目目录下放一个配置文件,
   写好各种参数
2. 支持环境变量——敏感信息比如 API 密钥
   从环境变量里读
3. 支持命令行参数——启动时可以用参数临时覆盖配置
4. 这三种方式有优先级:
   命令行参数 > 环境变量 > 配置文件 > 默认值

至少要能配置这些东西:
模型名称、API 密钥、最大对话轮数、
上下文窗口大小、工具超时时间、MCP 服务器列表。

没有配置文件也能正常启动,用合理的默认值。
$ cat .harness/config.toml
[model]
name = "claude-sonnet-4-20250514"
max_tokens = 8192

[engine]
max_turns = 100
context_window = 200000

[tools]
timeout = 30

$ harness --model claude-sonnet-4-20250514 --max-turns 50
[config] Loaded .harness/config.toml
[config] CLI override: model=claude-sonnet-4-20250514
[config] CLI override: max_turns=50
[config] Final: model=claude-sonnet-4-20250514, max_turns=50

You > /model
Current model: claude-sonnet-4-20250514

配置灵活了。但启动时如果 API 密钥没设、MCP 服务器连不上、记忆文件损坏——现在会直接崩溃。下一步加上健壮的启动流程。

Prompt 3:健壮的启动流程

帮我设计一个健壮的启动流程:

1. 按正确的顺序初始化每个模块——
   先加载配置,再初始化工具,再连 MCP 服务器,
   再加载权限、钩子、记忆,最后启动终端界面
2. 每个模块初始化失败时不要崩溃,
   记录错误,跳过这个模块继续启动
3. 启动完成后显示一个状态报告——
   哪些模块正常,哪些跳过了,为什么跳过
4. 必须有的模块(比如查询引擎、配置系统)
   如果出问题才真正报错退出
5. 加一个 --check 参数,只检查配置和连接是否正常,
   不进入对话模式

启动过程要快——用户不想等太久。
$ unset ANTHROPIC_API_KEY
$ harness
[ERROR] ANTHROPIC_API_KEY not set. Cannot start.
Hint: export ANTHROPIC_API_KEY=sk-ant-...

$ export ANTHROPIC_API_KEY=sk-ant-...
$ harness
[init] Config .............. OK
[init] Query engine ........ OK
[init] Built-in tools ...... OK (8 tools)
[init] MCP servers ......... WARN: 1/2 connected
       └─ database: connection refused
[init] Permissions ......... OK (12 rules)
[init] Hooks ............... OK (3 hooks)
[init] Memory .............. OK (5 entries)
[init] Terminal ............ OK

Harness v0.1.0 — ready (1 warning)

$ harness --check
Checking configuration...
[✓] Config file valid
[✓] API key present
[✓] Model accessible
[✓] Built-in tools loaded
[✗] MCP server "database" unreachable
[✓] Permissions rules valid
[✓] Memory files readable

Result: 6/7 checks passed, 1 warning

系统健壮了。最后一步——让别人能装上你的作品。

Prompt 4:打包发布

帮我做好发布准备,让别人能用一条命令装上直接用:

1. 完善 pyproject.toml——
   项目名、版本号、作者、描述、依赖、
   命令行入口点都配好
2. 加一个命令行入口——装完后在终端输入 harness
   就能直接启动
3. 用户第一次运行时,如果没有配置文件,
   自动创建一个带注释的默认配置
4. 写一个简单的安装说明,
   告诉用户怎么装、怎么配、怎么用
5. 确保能用 pip install 正常安装

打包格式用 Python 标准的 wheel 格式。
$ pip install -e .
Successfully installed harness-0.1.0

$ harness --version
Harness v0.1.0

$ harness --help
usage: harness [-h] [--version] [--model MODEL]
               [--max-turns N] [--check] [--serve]

AI Agent Runtime — 你的智能编程助手

options:
  --version       show version and exit
  --model MODEL   override AI model
  --max-turns N   max conversation turns
  --check         check config without starting
  --serve         start as MCP server

$ harness
Welcome to Harness v0.1.0!
First run detected — creating default config at .harness/config.toml
[init] Config .............. OK (using defaults)
[init] Query engine ........ OK
...

💡 四个 Prompt 做了什么

  • Prompt 1 建立了连接——所有模块串成一个整体
  • Prompt 2 给了灵活性——参数可配置,不用改代码
  • Prompt 3 给了健壮性——出错不崩溃,状态看得见
  • Prompt 4 给了产品形态——一条命令安装,开箱即用

现在你手里有了一个完整的产品。完整代码在 GitHub 仓库,对应 tag ch10-release

接下来我们回过头,理解你刚刚构建的东西。


深入理解

配置优先级

Prompt 2 做的”命令行参数 > 环境变量 > 配置文件 > 默认值”不是随便定的顺序,而是软件工程中的配置覆盖惯例——几乎所有成熟的 CLI 工具(Docker、Git、Kubernetes)都遵循这个优先级。

图 10-1:配置优先级——上层覆盖下层

  1. CLI 参数--model, --max-turns)— 最高优先级,覆盖一切
  2. 环境变量ANTHROPIC_API_KEY, HARNESS_MODEL)— 覆盖配置文件和默认值
  3. 配置文件.harness/config.toml, ~/.harness/config.toml)— 覆盖默认值
  4. 默认值claude-sonnet-4-20250514, max_turns=100)— 兜底配置

为什么是这个顺序?因为每一层对应不同的使用场景持久性

默认值是开发者预设的合理配置,保证”零配置也能跑”。它们硬编码在代码里,用户不需要操心。

配置文件是用户的日常偏好——“我这个项目一直用这个模型、这个超时、这些 MCP 服务器”。写一次,每次启动自动读取。

环境变量敏感信息和部署环境的载体——API 密钥不应该写在配置文件里(它会被提交到版本控制),而应该放在环境变量里。不同的部署环境(开发、测试、生产)通过环境变量切换。

命令行参数临时覆盖——“这次我想试试另一个模型""这次多跑几轮”。不影响配置文件,下次启动就恢复原样。

配置合并的实现很直接:

# harness/config.py — 配置合并逻辑
def load_config(cli_args: dict) -> Config:
    """按优先级合并配置:CLI > env > file > defaults"""
    # 1. 从默认值开始
    config = DEFAULT_CONFIG.copy()

    # 2. 叠加配置文件
    config_file = find_config_file()
    if config_file:
        file_config = toml.load(config_file)
        config = deep_merge(config, file_config)

    # 3. 叠加环境变量
    env_config = load_env_config()
    config = deep_merge(config, env_config)

    # 4. 叠加 CLI 参数(最高优先级)
    config = deep_merge(config, cli_args)

    return Config(**config)

deep_merge 是关键——它不是简单的字典覆盖,而是递归合并。如果配置文件里定义了 [tools] timeout = 30,CLI 传了 --model xxx,合并后 tools.timeout 保留 30,model 被覆盖为 xxx。互不干扰。

配置文件的位置

配置文件去哪里找?按照惯例,搜索顺序是:

  1. 项目级——当前目录下的 .harness/config.toml,只对这个项目生效
  2. 用户级——~/.harness/config.toml,对这个用户的所有项目生效
  3. 系统级——/etc/harness/config.toml,对这台机器的所有用户生效

找到第一个就用,不再往下找。这和 Git 的 .gitconfig 搜索逻辑一致——先看项目级(.git/config),再看用户级(~/.gitconfig),再看系统级(/etc/gitconfig)。

Claude Code 也遵循同样的模式:项目级 .claude/settings.json 覆盖用户级 ~/.claude/settings.json

启动顺序

Prompt 3 要求”按正确的顺序初始化”。为什么顺序重要?因为模块之间有依赖关系——权限系统需要知道有哪些工具才能匹配规则,钩子需要在查询引擎开始前就注册好,记忆加载需要在第一次对话之前完成。

图 10-2:Harness 启动顺序——每一步都依赖前一步的结果

  1. 加载配置 → 读取 CLI 参数、环境变量、配置文件,合并为最终配置
  2. 初始化查询引擎 → 创建 API 客户端,验证 API 密钥和模型可用性
  3. 注册内置工具 → 把 file_read、bash、grep 等工具注册到 ToolRegistry
  4. 连接 MCP 服务器 → 启动外部服务器进程,发现工具,合并到 ToolRegistry
  5. 加载权限规则 → 读取规则文件,绑定到 ToolRegistry 的工具列表
  6. 注册钩子与技能 → 加载钩子配置,注册到对应的生命周期事件
  7. 加载记忆 → 读取热记忆文件,准备注入系统提示词
  8. 启动终端界面 → 初始化 Rich 渲染器,显示启动报告,进入对话循环

注意第 4 步(连接 MCP 服务器)必须在第 3 步(注册内置工具)之后——因为 MCP 工具要合并到同一个 ToolRegistry。第 5 步(权限规则)必须在第 4 步之后——因为权限规则可能匹配 MCP 工具。第 6 步(钩子)必须在第 7 步(记忆)之前——因为 session_start 钩子可能会触发记忆加载。

这种**有向无环图(DAG)**的依赖关系在所有复杂系统的启动过程中都存在:操作系统先启动内核再启动用户服务、Web 框架先加载路由再接受请求、数据库先恢复日志再打开端口。

优雅降级

“MCP 服务器连不上”不应该阻止整个系统启动。设计原则是区分关键依赖可选依赖

模块级别失败时的行为
配置系统关键报错退出——没有配置什么都跑不了
API 客户端关键报错退出——没有 API 密钥就没法对话
内置工具关键报错退出——没有工具的 Agent 是残废的
MCP 服务器可选记录警告,跳过,继续启动
权限规则可选使用默认规则(全部需要确认)
钩子可选记录警告,跳过,功能不受影响
记忆可选从空白记忆开始,不影响对话
终端渲染降级回退到纯文本输出

关键依赖失败就退出并给出清晰的错误信息。可选依赖失败就降级运行——少了几个 MCP 工具,Agent 还是能对话、能用内置工具。这种优雅降级的设计让系统在各种环境下都能尽可能地工作。

测试策略

发布前要测试。但 AI Agent 的测试和普通软件不一样——AI 的回复是非确定性的,你没法写一个测试断言”AI 一定会说这句话”。那怎么测?

答案是分层测试——不同层面用不同的测试方法:

层级测什么怎么测确定性
单元测试工具注册、配置解析、权限匹配等纯逻辑标准 pytest,mock 外部依赖100%
集成测试模块间的连接——工具调用过权限、MCP 工具合并启动真实模块,mock API 调用
端到端测试完整的对话流程——启动、对话、工具调用、退出真实 API + 录制回放中等
行为测试AI 是否正确使用工具、是否遵守权限、输出是否合理人工审查 + 模式匹配

单元测试:确定性的部分

系统中大量的逻辑是确定性的——不涉及 AI。这些可以用标准的单元测试覆盖:

# tests/test_config.py — 配置优先级测试
def test_cli_overrides_file():
    file_config = {"model": "haiku", "max_turns": 100}
    cli_args = {"model": "sonnet"}
    result = merge_config(file_config, cli_args)
    assert result["model"] == "sonnet"       # CLI 胜出
    assert result["max_turns"] == 100         # 文件保留

def test_permission_rule_matching():
    rule = Rule(tool="bash", command="rm *", action="deny")
    assert rule.matches("bash", {"command": "rm -rf /"})
    assert not rule.matches("file_read", {"path": "x"})

这类测试跑得快、结果稳定、覆盖面广。你的 Agent 里有大量这样的纯逻辑——配置解析、权限匹配、工具注册、钩子触发条件、命令解析、记忆文件格式。先把确定性的部分测到 90% 以上覆盖率

端到端测试:录制与回放

涉及 AI 的测试用录制回放模式:第一次跑测试时真正调用 API,把请求和响应录下来存成文件。以后跑测试时回放录制的响应,不再调 API——既省钱又确定。

# tests/test_e2e.py — 录制回放测试
@pytest.fixture
def recorded_session():
    """加载录制好的会话"""
    return load_recording("tests/recordings/basic_chat.json")

def test_basic_conversation(recorded_session):
    app = create_app(config=test_config)
    result = app.replay(recorded_session)
    assert result.exit_code == 0
    assert result.turns >= 1
    assert "error" not in result.output.lower()

行为测试:模式匹配

AI 的输出虽然不确定,但可以验证模式——“AI 应该调用了某个工具""AI 不应该执行危险命令""AI 的回复应该包含某些关键信息”:

# tests/test_behavior.py — 行为模式验证
def test_ai_uses_file_read_for_code_questions():
    response = run_session("帮我看看 main.py 里写了什么")
    assert any(
        call.tool == "file_read"
        for call in response.tool_calls
    ), "AI should use file_read for code questions"

def test_ai_respects_permission_denial():
    response = run_session(
        "删除所有测试文件",
        permission_response="deny",
    )
    assert not any(
        call.tool == "bash" and "rm" in call.args.get("command", "")
        for call in response.tool_calls
    ), "AI should not execute rm after denial"

完整架构回顾

十章走下来,让我们站远一点,看看整个系统的全貌。

图 10-3:Harness 完整架构——从用户输入到模块协作的全景

                    ┌──────────┐
                    │   用户   │
                    └────┬─────┘


              ┌─────────────────────┐
              │     终端界面        │
              │ Rich 渲染·命令·多行  │
              └────────┬────────────┘


              ┌─────────────────────┐
              │     查询引擎        │
              │ while(true)·流式·压缩│
              └──┬─────┬─────┬──────┘
                 │     │     │
         ┌───────┘     │     └───────┐
         ▼             ▼             ▼
   ┌──────────┐  ┌──────────┐  ┌──────────┐
   │ 工具系统 │  │Agent 编排│  │ 权限系统 │
   │定义·注册 │  │委托·后台 │  │分级·规则 │
   └────┬─────┘  └────┬─────┘  └────┬─────┘
        │             │             │
        ▼             ▼             ▼
   ┌──────────┐  ┌──────────┐  ┌──────────┐
   │ MCP 集成 │  │钩子与技能│  │ 记忆系统 │
   │客户端·服端│  │生命周期  │  │热记忆·冷 │
   └────┬─────┘  └────┬─────┘  └────┬─────┘
        │             │             │
        └─────────────┼─────────────┘

        ┌───────────────────────────┐
        │        配置系统           │
        │ CLI·环境变量·配置文件·默认值│
        └───────────────────────────┘

从上往下看:

用户通过终端界面输入(第 9 章),终端把输入交给查询引擎(第 2 章)。查询引擎是核心循环——它调用 LLM,LLM 返回工具调用请求时,引擎通过工具系统(第 3 章)执行。执行前要过权限系统(第 4 章)的检查。工具列表包含内置工具和通过MCP 集成(第 8 章)接入的外部工具。

复杂任务由Agent 编排(第 5 章)拆分给子 Agent。跨会话的上下文由记忆系统(第 6 章)持久化。整个流程中,钩子与技能(第 7 章)在关键时刻插入自定义逻辑。所有模块的行为由底层的配置系统(本章)控制。

这不是一个理论架构图——这是你在过去十章中亲手构建的系统

💡 核心概念:模块化的代价与收益

九个模块、九章内容——为什么要分这么细?直接写一个大文件不行吗?

行。但只能行一次。

短期看,一个大文件更快——不用想模块边界,不用定义接口,想到哪写到哪。但当你想加一个新的 MCP 服务器、改一条权限规则、换一种终端渲染方式时,你必须在一团纠缠的代码里小心翼翼地修改,祈祷不会弄坏别的功能。

长期看,模块化的收益是变更的局部性——改权限规则不影响终端渲染,加 MCP 工具不影响记忆系统。每个模块有清晰的边界和接口,修改一个模块时你只需要理解这一个模块的代码。

这正是 Claude Code 的做法:五万行代码分成 core/tools/permissions/hooks/memory/skills/ 等目录,每个目录独立演进。它能从最初的版本迭代到今天的复杂度,靠的就是这种模块化纪律。

Claude Code 的产品化

我们从九个模块组装出了一个可运行的 Agent。Claude Code 做了同样的事——但从”可运行”到”每天被数百万开发者使用的产品”,它还多走了很多步。

分发方式

Claude Code 通过 npm 分发——npm install -g @anthropic-ai/claude-code,一条命令全球可用。npm 是 JavaScript/TypeScript 生态的包管理器,安装后在 PATH 里注册 claude 命令。

为什么不用独立安装包?因为 npm 解决了依赖管理跨平台两个难题。Node.js 运行在 macOS、Linux、Windows 上,npm 自动处理平台差异。

我们的 harness 用 pip——Python 生态的等价物。pip install harness 安装后注册 harness 命令。原理完全一样,只是生态不同。

版本管理

Claude Code 遵循语义化版本(semver):MAJOR.MINOR.PATCH

  • PATCH(0.0.x)——修 bug,不改接口
  • MINOR(0.x.0)——加功能,向后兼容
  • MAJOR(x.0.0)——改接口,可能不兼容

每次发版都有 changelog 记录变更。用户可以锁定版本(npm install @anthropic-ai/claude-code@1.2.3)避免意外升级。

自动更新

Claude Code 在启动时检查是否有新版本——如果有,提示用户更新。这个检查是非阻塞的:在后台发一个 HTTP 请求查最新版本号,和启动初始化并行进行。如果网络不通或者超时,就跳过,不影响正常使用。

遥测与反馈

产品需要知道用户怎么用它。Claude Code 收集匿名使用数据——用了哪些功能、平均对话轮数、最常用的工具——帮助团队做产品决策。关键原则:

  • 可选退出——用户可以关闭遥测
  • 匿名化——不收集对话内容和代码
  • 透明——文档里明确说明收集了什么

从 Harness 到产品

你现在手里有了一个完整的 Agent Harness。接下来往哪走?取决于你想用它做什么。

图 10-4:从 Harness 到产品的演进路线

  1. [已完成] 核心功能 — 查询引擎 · 工具 · 权限 · 编排 · 记忆 · 钩子 · MCP · 终端
  2. [已完成] 产品化 — 配置 · 启动 · 测试 · 打包 ← 当前位置
  3. [下一步] 领域定制 — 针对特定场景定制 Prompt · 工具 · 技能
  4. [进阶] Web 界面 — 事件驱动已就绪,加 WebSocket 前端
  5. [远期] 多用户部署 — 认证 · 隔离 · 计费 · 监控

领域定制

Harness 是通用框架,但真正的价值在领域定制。几个方向:

代码审查 Agent——预装 code-review 技能,配置只读工具权限,加上 Git 集成钩子,专门做代码审查。

运维 Agent——接入服务器监控的 MCP 工具,配置严格的权限规则(只能查看不能修改),专门做故障排查。

文档 Agent——预装文档生成技能,接入 Markdown/Typst 渲染工具,专门帮团队写和维护文档。

每种定制都不需要改核心代码——通过配置文件、技能包、钩子、MCP 工具就能完成。这就是模块化架构的回报。

Web 界面

第 9 章我们用事件驱动架构解耦了业务逻辑和终端渲染。要做 Web 界面,只需要写一个新的事件消费者——监听同样的事件,通过 WebSocket 推送到浏览器:

图 10-5:同一套事件驱动架构适配多种界面

  1. 业务逻辑 → yield Event(…)
  2. 事件分发器 → 路由到消费者
  3. 终端 / Web / API → 各自渲染

核心循环一行不改,换个渲染器就从终端应用变成了 Web 应用。

多用户部署

如果要把你的 Agent 部署为服务——多个用户同时使用——还需要考虑:

  • 认证——谁能用?用户身份怎么验证?
  • 隔离——A 用户的对话不能泄露给 B 用户
  • 计费——每个用户用了多少 token、该收多少钱
  • 监控——系统健康状况、错误率、响应时间

这些超出了本书的范围,但架构已经为此做好了准备——配置系统支持多租户、权限系统支持角色、事件系统支持审计日志。


延伸思考

这是本书的最后三个问题。不急着回答,带着它们去实践:

  1. 我们的配置系统用了”CLI > 环境变量 > 配置文件 > 默认值”的优先级。但如果有些配置不应该被 CLI 参数覆盖呢——比如安全相关的权限规则,你不希望有人用 --no-permissions 就绕过整个权限系统。你会怎么设计”不可覆盖的配置”?
  2. 你现在有了一个完整的 Agent Harness,也看了 Claude Code 的架构。如果让你从零重新设计,你会做哪些不同的决策?哪些模块你会合并,哪些你会进一步拆分?
  3. AI Agent 的能力边界在快速扩张——从文本对话到代码编写到工具使用到多 Agent 协作。作为 Harness 的构建者,你觉得下一个需要加入的”模块”是什么?为什么?

章节小结

这是本书的最后一章,也是整个旅程的终点。让我们回顾走过的路:

  • 第 1 章我们认识了 Harness——它不是 wrapper,不是 prompt engineering,而是 AI Agent 的运行时编排系统
  • 第 2 章我们造出了心脏——一个 while(true) 循环驱动的查询引擎,支持流式输出和上下文压缩
  • 第 3 章我们装上了手脚——工具系统让 Agent 能读文件、写文件、跑命令、搜代码
  • 第 4 章我们装上了刹车——权限系统用风险分级和规则引擎确保 Agent 不会失控
  • 第 5 章我们学会了派活——Agent 编排让复杂任务拆给多个 AI 分头完成
  • 第 6 章我们赋予了记忆——热记忆和冷记忆让 Agent 跨会话保持上下文
  • 第 7 章我们打开了扩展——钩子和技能让 Agent 的行为可以无限定制
  • 第 8 章我们连接了生态——MCP 协议让 Agent 既能借用别人的工具,也能暴露自己的能力
  • 第 9 章我们打磨了体验——彩色输出、进度反馈、命令系统、多行输入让 Agent 用着舒服
  • 第 10 章我们完成了组装——配置、启动、测试、打包,从一堆模块变成了一个产品

十章,三十多个 Prompt,一个完整的 AI Agent Runtime。

你不只是读了一本关于 AI Agent 的书——你造了一个。它能对话、能动手、有权限、会记忆、可扩展、连生态、体验好、一条命令安装。

这个 Harness 是你的。拿它去定制、去部署、去改造。把它变成代码审查助手、运维诊断专家、文档写作伙伴——或者任何你能想到的东西。

AI Agent 的时代刚刚开始。你现在不只是用户,你是构建者

English EN 简体中文 ZH