# 让智能体在本地代码仓库中完成一次缺陷修复

在代码开发、数据处理和日常运维中，很多任务都依赖已经配置好的工作环境：文件保存在自己的电脑或服务器上，运行需要特定的依赖和工具，有些服务还只能通过内网访问。如果为了让智能体执行任务，必须重新上传资料、安装依赖或迁移项目，准备成本会很高，也容易出现环境不一致的问题。

MOI 的自有运行环境让你把这些已有设备接入平台，并在对话中选择它们作为任务的执行环境。智能体可以在指定工作目录中使用现有文件、依赖和命令行工具完成操作，你则可以在原来的环境中检查结果，不必为每次任务重新搭建一套环境。

下面以“修复本地 Python 项目的一个缺陷”为例，演示如何使用自有运行环境。你会准备一个带有边界条件缺陷的示例仓库，将项目目录接入 MOI，让智能体先定位问题；确认方案后，再让它修改代码、重新运行测试，最后在本地审查代码差异和修复报告。

## 你将完成什么

* 在电脑上准备一个可以稳定复现缺陷的本地代码仓库；

* 安装 `astra-edge`，将这个代码仓库接入为 MOI 自有运行环境；

* 在新对话中选择该运行环境；

* 让智能体运行测试、定位根因，并在修改前给出修复计划；

* 明确确认后，让智能体修改代码并重新运行测试；

* 在本地终端审查代码差异和智能体生成的修复报告。

## 开始前准备

* 准备一个 MOI 账号，并进入可以使用智能体和运行环境的工作区；

* 准备一台可以访问 MOI 服务的 macOS 或 Linux 设备。Windows 用户请在 WSL 中使用 Linux 版本；

* 确认设备已安装 Python 3 和 Git，并且可以在终端运行 `python3 --version` 和 `git --version`；

* 确认工作区中有可用的通用智能体和模型。

:::{warning}
自有运行环境会在你的设备上执行智能体请求的文件和命令操作。第一次体验请使用本教程提供的独立示例仓库，不要从主目录、系统目录或含有密钥、客户数据、生产配置的真实项目目录启动连接。

连接命令包含访问凭证，请妥善保存，并仅在准备接入的设备上运行。

本地执行不等于数据不会离开设备。智能体读取的代码、测试输出和命令结果可能会发送给模型用于推理，请遵守所在组织的代码和数据使用规则。
:::

## 真正可用前需要完成什么

自有运行环境不是创建一个名称后就立即可用。你需要依次打通下面三层：

| 层次 | 需要做什么 | 如何确认 |
| --- | --- | --- |
| 安装客户端 | 在目标电脑安装 `astra-edge`。同一台电脑通常只需安装一次 | `astra-edge` 可以在本机运行 |
| 建立连接 | 进入希望交给智能体工作的目录，执行 MOI 为该环境生成的连接命令，并保持终端运行 | 运行环境列表显示可用，并出现已连接时长 |
| 选择环境 | 在新对话的运行环境选择器中选中该自有环境 | 发送消息前，输入区显示目标环境名称 |

只安装 `astra-edge`，设备还没有连接到 MOI；只创建环境名称但不运行连接命令，环境仍会停留在待连接状态。只有连接命令持续运行、MOI 显示环境可用，并且当前对话选中了它，智能体才会在这台设备的目标目录中执行任务。

本教程使用运行环境窗口提供的安装脚本。脚本版本由 MOI 发布目录统一管理，其他部署请使用对应环境提供的安装入口。

## 操作步骤

### 1. 准备一个测试失败的本地项目

在准备接入的电脑上打开终端，执行以下命令：

```bash
mkdir -p "$HOME/moi-runtime-tutorial"
cd "$HOME/moi-runtime-tutorial"

cat > shipping.py <<'EOF'
from decimal import Decimal

FREE_SHIPPING_THRESHOLD = Decimal("100.00")
STANDARD_SHIPPING_FEE = Decimal("12.00")


def calculate_total(subtotal: Decimal) -> Decimal:
    """Return the order total including shipping."""
    if subtotal > FREE_SHIPPING_THRESHOLD:
        return subtotal
    return subtotal + STANDARD_SHIPPING_FEE
EOF

cat > test_shipping.py <<'EOF'
import unittest
from decimal import Decimal

from shipping import calculate_total


class CalculateTotalTest(unittest.TestCase):
    def test_below_threshold_adds_shipping(self):
        self.assertEqual(calculate_total(Decimal("99.99")), Decimal("111.99"))

    def test_threshold_qualifies_for_free_shipping(self):
        self.assertEqual(calculate_total(Decimal("100.00")), Decimal("100.00"))

    def test_above_threshold_qualifies_for_free_shipping(self):
        self.assertEqual(calculate_total(Decimal("120.00")), Decimal("120.00"))


if __name__ == "__main__":
    unittest.main()
EOF

git init -q
git add shipping.py test_shipping.py
```

运行测试，确认问题可以稳定复现：

```bash
python3 -m unittest -v
```

测试结果应显示 3 个用例中有 1 个失败：订单金额刚好为 `100.00` 时，预期总金额仍为 `100.00`，实际却变成 `112.00`。

```{image} ../assets/images/tutorials/agent-self-hosted-runtime-test-failure.png
:width: 100%
:alt: 本地终端运行 Python 单元测试；金额恰好为免运费门槛时，预期 100.00，实际 112.00，3 个测试中有 1 个失败。
```

现在执行：

```bash
pwd
git status --short
```

确认当前目录是 `moi-runtime-tutorial`，并且可以看到已经加入 Git 暂存区的 `shipping.py` 和 `test_shipping.py`。暂存区将作为修改前的基线，方便稍后审查智能体产生的代码差异。

```{image} ../assets/images/tutorials/agent-self-hosted-runtime-project-baseline.png
:width: 100%
:alt: 本地终端显示项目目录 moi-runtime-tutorial，以及已加入 Git 暂存区的 shipping.py 和 test_shipping.py。
```

运行测试后可能还会出现 `?? __pycache__/`；这是 Python 自动生成的缓存目录，不要将它加入暂存区，也不影响后续审查源码差异。

本教程后续的修改和修复报告都会保存在这个目录。请保持该终端窗口可用。

完成标志：`python3 -m unittest -v` 稳定显示 1 个失败用例，并且当前目录是 `moi-runtime-tutorial`。

### 2. 创建自有运行环境

1. 登录 MOI，进入本次教程使用的工作区。

2. 在左侧导航进入 **资源中心 → 运行环境**。

   ```{image} ../assets/images/tutorials/agent-self-hosted-runtime-entry.png
   :width: 100%
   :alt: 资源中心的运行环境页面，下方为自有运行环境区域，右侧提供接入自有环境按钮。
   ```

3. 找到 **自有运行环境**，点击 **接入自有环境**。

4. 输入便于识别的环境名称，例如 `本地代码修复`，然后确认接入。

MOI 会打开“接入自有运行环境”窗口，其中包含本次接入专用的连接命令。当前线上页面可能只提供连接命令，不显示客户端安装入口；这种情况下按下一步独立安装即可。连接命令包含访问凭证且只显示一次，请保持窗口打开。

```{image} ../assets/images/tutorials/agent-self-hosted-runtime-create.png
:width: 100%
:alt: 接入自有运行环境窗口，展示部分打码的连接命令，以及展开的安装或更新 astra-edge 区域。
```

如果当前账号看不到接入按钮，请先确认所在工作区是否正确，再请工作区管理员检查运行环境相关权限。

完成标志：页面显示“接入自有运行环境”窗口，并生成了连接命令。

### 3. 安装 `astra-edge` 客户端

`astra-edge` 是保持 MOI 与当前设备连接的客户端。同一台电脑通常只需安装一次；创建环境名称或获得连接命令并不会自动安装它。

以下命令会识别 macOS/Linux 和 CPU 架构，安装或更新 `astra-edge`，并保持终端的 PATH 不变，不需要管理员权限。

在准备接入的电脑上执行：

```bash
curl --proto '=https' --proto-redir '=https' --tlsv1.2 -fsSL \
  'https://astra-suite.oss-cn-hangzhou.aliyuncs.com/bundles/2026.09.21.5/install.sh' |
  sh -s -- --no-modify-path
```

安装完成后检查版本：

```bash
"$HOME/.local/share/moi/client/bin/astra-edge" --version
```

```{image} ../assets/images/tutorials/agent-self-hosted-runtime-install.png
:width: 100%
:alt: 本地终端执行安装脚本后完成客户端更新，并通过版本检查显示 astra-edge 0.2.7。
```

完成标志：在目标电脑执行 `"$HOME/.local/share/moi/client/bin/astra-edge" --version` 可以看到版本信息。此时只是安装完成，尚未连接 MOI。

### 4. 在项目目录连接到 MOI

先回到步骤 1 创建的项目目录：

```bash
cd "$HOME/moi-runtime-tutorial"
pwd
```

确认 `pwd` 指向该目录后，回到 MOI 的“接入自有运行环境”窗口，复制 **连接到 MOI** 下的完整连接命令，在当前终端中执行。连接命令是 MOI 为本次环境生成的，包含访问凭证；本文不提供可复用的固定连接命令。

下图仅展示连接成功的日志，图中的工作目录与本教程不同；实际操作时，请确认日志中的工作目录指向你的 `moi-runtime-tutorial`。

```{image} ../assets/images/tutorials/agent-self-hosted-runtime-connect.png
:width: 100%
:alt: 本地终端运行 MOI 连接命令，显示认证成功和 Edge agent ready 日志，以及当前工作目录。
```

保持该命令和终端持续运行。回到 MOI 的运行环境列表，等待 `本地代码修复` 显示为 **可用**，并出现已连接时长。

```{image} ../assets/images/tutorials/agent-self-hosted-runtime-available.png
:width: 100%
:alt: 运行环境页面中，自有运行环境“本地代码修复”显示为可用，并显示已连接时长。
```

智能体会以执行连接命令时的当前目录作为工作目录。如果在其他目录执行，请先停止连接，切换到正确目录后重新执行。

如果你关闭了接入窗口且没有保存连接命令，可在环境列表中点击刷新 Token 的按钮获取新命令。刷新后应使用新命令重新连接，旧命令不要继续使用。

完成标志：`本地代码修复` 显示为可用或已连接，运行连接命令的终端保持打开。

### 5. 在新对话中选择自有运行环境

1. 点击左侧 **新对话**。

2. 在输入区确认已选择工作区提供的通用智能体。

3. 打开输入区的运行环境选择器。不要保留 **默认**，在 **自有运行环境** 分组中选择 `本地代码修复`。

4. 确认选择器显示 `本地代码修复`，并带有已连接状态。

只有已经就绪的环境会出现在选择器中。如果找不到刚创建的环境，请返回 **资源中心 → 运行环境**，检查连接命令是否仍在运行、设备是否在线，以及页面状态是否已经变为可用。

<!-- 截图建议：新对话输入区展开运行环境选择器，并选中“本地代码修复”。 -->

完成标志：发送消息前，输入区显示的运行环境是 `本地代码修复`。

### 6. 让智能体复现问题并定位根因

将以下内容粘贴到输入框并发送：

```text
你正在排查当前本地代码仓库中的失败测试。请完成以下调查：

1. 先运行 pwd 和 git status --short，确认当前项目和修改基线。
2. 阅读 shipping.py 和 test_shipping.py。
3. 运行 python3 -m unittest -v，记录失败用例、预期值和实际值。
4. 根据代码和测试定位根因，并提出最小修复方案。
5. 说明修复后需要重新执行哪些验证。

这一轮只调查和提出方案。不要修改任何文件，不要安装依赖，不要提交 Git 变更，也不要访问当前工作目录之外的内容。
```

这一次，智能体不是根据你粘贴的一小段代码猜答案，而是在你的设备上读取完整文件并执行真实测试。等待调查完成，不要关闭运行 `astra-edge` 的终端。

检查智能体的诊断是否包含以下证据：

* 当前工作目录是 `moi-runtime-tutorial`；

* 实际运行了 3 个测试，其中 `test_threshold_qualifies_for_free_shipping` 失败；

* 金额为 `100.00` 时，预期结果是 `100.00`，实际结果是 `112.00`；

* 根因是 `shipping.py` 使用了严格大于判断，恰好等于免运费门槛的订单没有进入免运费分支；

* 最小修复方案是只调整边界判断，不修改测试，也不引入新依赖。

下面是一次诊断结果示例，依次展示项目基线与失败测试、根因分析，以及修复方案和验证计划。这一轮只提出方案，尚未修改代码。

```{image} ../assets/images/tutorials/agent-self-hosted-runtime-diagnosis-baseline.png
:width: 100%
:alt: 对话中已选择本地代码修复环境，智能体确认项目目录和 Git 基线，并复现 3 个测试中有 1 个失败。
```

```{image} ../assets/images/tutorials/agent-self-hosted-runtime-diagnosis-root-cause.png
:width: 100%
:alt: 智能体核对金额为 100.00 时预期 100.00、实际 112.00，定位到严格大于比较造成的边界条件错误，并提出改为大于等于。
```

```{image} ../assets/images/tutorials/agent-self-hosted-runtime-diagnosis-plan.png
:width: 100%
:alt: 智能体给出只修改一行判断的最小修复方案和修复后验证计划，并明确本轮尚未修改文件、安装依赖或提交 Git。
```

此时在本地另开一个终端，执行：

```bash
cd "$HOME/moi-runtime-tutorial"
git diff -- shipping.py test_shipping.py
```

命令不应输出任何差异，证明智能体遵守了“只调查、不修改”的要求。如果出现修改，先不要继续；检查差异并恢复到你确认的基线后，再开始下一步。

```{image} ../assets/images/tutorials/agent-self-hosted-runtime-diagnosis-no-diff.png
:width: 100%
:alt: 本地终端执行 git diff -- shipping.py test_shipping.py 后直接返回命令提示符，没有输出差异。
```

如果智能体提示找不到项目，先核对回复中的 `pwd`。路径不正确时，在本地终端停止当前连接，进入 `moi-runtime-tutorial` 后重新运行连接命令，再开启一个新对话重试。

完成标志：智能体给出有测试输出支撑的根因和最小修复方案，而且工作区文件尚未发生变化。

### 7. 确认方案并让智能体完成修复

确认诊断无误后，在同一对话中发送：

```text
我已核对诊断，确认按最小方案修复。现在请：

1. 只修改 shipping.py，不要修改 test_shipping.py。
2. 修复金额恰好等于免运费门槛时仍收取运费的问题。
3. 运行 python3 -m unittest -v，确认全部测试通过。
4. 运行 git diff --check 和 git diff -- shipping.py，检查改动质量和范围。
5. 在当前目录创建 repair-report.md，记录：失败现象、根因、实际修改、测试结果和仍需人工确认的事项。
6. 在回复中给出修改文件、测试结果和报告的完整路径。

不要提交或推送 Git 变更，不要修改测试，不要访问当前工作目录之外的内容。
```

智能体现在会在自有运行环境中修改真实文件，并使用同一套本地工具链验证修改。检查结果是否满足：

* 3 个测试全部通过；

* 只有 `shipping.py` 的业务判断被修改；

* `test_shipping.py` 保持不变；

* `git diff --check` 没有报告格式错误；

* 当前目录生成了 `repair-report.md`；

* 智能体没有自行提交或推送代码。

下面是确认方案后的修复结果示例，展示一行代码差异、全部测试通过，以及生成的修复报告。

```{image} ../assets/images/tutorials/agent-self-hosted-runtime-repair-tests.png
:width: 100%
:alt: 用户确认修复方案后，智能体将 shipping.py 中的严格大于改为大于等于，并展示 3 个测试全部通过。
```

```{image} ../assets/images/tutorials/agent-self-hosted-runtime-repair-report.png
:width: 100%
:alt: 智能体展示通过的测试和差异检查，以及 repair-report.md 的路径与内容摘要，并确认未修改测试、未提交或推送代码。
```

完成标志：智能体报告 3 个测试全部通过，并确认只修改了 `shipping.py`、生成了 `repair-report.md`。

### 8. 在本地审查智能体的交付结果

打开另一个终端窗口，执行：

```bash
cd "$HOME/moi-runtime-tutorial"
git status --short
git diff --check
git diff -- shipping.py test_shipping.py
python3 -m unittest -v
cat repair-report.md
```

确认满足以下条件：

* `git diff` 中只有 `shipping.py` 的条件判断发生变化；

* 差异应当等价于把 `subtotal > FREE_SHIPPING_THRESHOLD` 改为 `subtotal >= FREE_SHIPPING_THRESHOLD`；

* `test_shipping.py` 没有被修改；

* 再次运行测试仍然显示 3 个用例全部通过；

* `repair-report.md` 中的结论与实际代码差异、测试结果一致。

下面是本地审查结果示例。首张截图顶部的 `compinit` / `compdef` 提示属于终端初始化问题，与本次修复无关。

```{image} ../assets/images/tutorials/agent-self-hosted-runtime-local-review-tests.png
:width: 100%
:alt: 本地终端显示 Git 状态、shipping.py 中由大于改为大于等于的一行差异、3 个测试全部通过，以及修复报告的失败现象和根因部分。
```

```{image} ../assets/images/tutorials/agent-self-hosted-runtime-local-review-report.png
:width: 100%
:alt: 本地终端继续展示修复报告，包括实际代码修改、通过的测试、质量检查及仍需人工确认的事项。
```

这些修改只留在你的本地工作区中，没有被自动提交或推送。你可以继续人工审查、补充测试，再决定是否进入团队原有的代码评审流程。

完成标志：你能在本地看到最小代码差异、通过的测试和可追溯的修复报告，而且远端仓库没有发生变化。

### 9. 结束连接

本次教程完成后，回到运行 `astra-edge` 的终端，按 `Ctrl+C` 结束连接。MOI 中的环境随后会显示为未连接，也不会再出现在新对话的可用运行环境列表中。

以后需要继续使用时，进入同一工作目录，再运行该环境当前有效的连接命令。若连接凭证已经过期，或原命令已经丢失，请在 MOI 的运行环境列表中刷新 Token，并改用新生成的命令。

如果不再需要这个环境，可以在 **资源中心 → 运行环境** 中删除。删除环境不会自动删除电脑上的工作目录或本教程生成的文件；如需删除本地文件，请先自行确认内容。

## 教程完成

你已经把一个真实可执行的代码仓库接入为 MOI 自有运行环境，并完成了“复现失败 → 基于证据定位根因 → 人工确认 → 修改源码 → 重新运行测试 → 本地审查交付”的完整闭环。

这正是自有运行环境的核心价值：它把智能体带到工作发生的地方。智能体可以复用你已经配置好的代码、依赖、编译器、测试工具、脚本和网络条件，而结果仍然落在原来的工作目录中，供你使用熟悉的 Git 和测试流程审查。

完成本教程后，你可以把相同方法用于分析真实仓库、修复缺陷、升级依赖、执行数据脚本或排查只能从内网访问的服务。对于不依赖本地设备、希望由平台统一维护算力和网络策略的任务，则可以选择托管运行环境。
