Agent 开发入门:工具调用循环、上下文与工程化落地

写 Agent 时,很多人一上来就纠结「用哪个框架」。更值得先想清楚的是:模型负责推理,工具负责改世界;中间那一圈「观察 → 决策 → 调用 → 再观察」怎么收口。 框架只是把这圈循环写得更省事。本文按工程视角拆开这套循环,并落到 Python / TypeScript、MCP、Skill(可复用流程说明书)上常见的实现选择。

本文不讲「万能自主 AI」。默认场景是:IDE / CLI 里由人触发、有权限边界、可审计的编码与运维助手——和博客站里那篇 MCP 与 Skill 驱动下的跨端转换 同一类问题域。


1. Agent 到底多出来一层什么

聊天补全:用户一问,模型一答,结束。

Agent:模型在回答之前(或之间)可以 多次调用工具,把工具结果写回上下文,再继续推理,直到它认为可以给出最终答复,或被策略强制停下。

一张极简结构(内联 SVG,避免 Mermaid 中文裁切):

Agent 循环 用户任务进入 LLM,LLM 可调用工具并读回结果,直到输出最终答复。 用户任务 一句话需求 / 指令 LLM 计划 · 选工具 · 汇总结果 可多次循环 工具 读文件 · 跑命令 · 查 API 有权限与超时 输出最终答复 tool call observation

差别不在「会不会说话」,而在:

维度 普通对话 Agent
上下文来源 主要靠用户粘贴 模型可主动拉仓库、日志、文档
副作用 通常没有 写文件、开 PR、调外部系统(需权限)
失败处理 用户再追问 循环里读错误信息、改参数重试
停机条件 一轮结束 预算(步数 / token / 时间)+ 明确结束态

若某次任务 不需要工具,硬套 Agent 只会更慢、更贵;有时「单次推理 + 你自己写好的脚本」反而更稳。


2. 工具调用循环:实现上绕不开的几件事

无论用 LangChain / LangGraph、自研,还是 IDE 内置 Agent,内核多半长这样:

  1. 组装消息:系统提示 + 历史 + 当前任务 +(可选)可用工具 schema。
  2. 调模型:要求返回「纯文本」或「结构化 tool call」。
  3. 若有 tool call:校验参数 → 执行 → 把结果以 tool 角色写回消息列表。
  4. 若无 tool call:视为最终答案,退出。
  5. 防护:最大步数、单工具超时、敏感路径黑名单、是否允许联网。

伪代码(语言无关):

1
2
3
4
5
6
7
8
9
10
messages = [system, user_task]
for step in 1..MAX_STEPS:
resp = llm(messages, tools=TOOL_SCHEMAS)
if resp.tool_calls:
for call in resp.tool_calls:
result = run_tool(call.name, call.args) # 这里要做权限与超时
messages.append(tool_result(call.id, result))
continue
return resp.text
raise BudgetExceeded

落地时容易踩的坑:

  • 工具描述含糊:模型会乱选工具或乱填参数。schema 的 description 和「什么时候不该用」写清楚,比堆工具数量重要。
  • 结果太长:把整份 build.log 塞回上下文,下一步推理会糊。要对日志做截断、摘要、或只回错误附近几行。
  • 无退出条件:模型反复「再试一下」。步数上限 +「连续 N 次同类失败则停并汇报」比指望它自觉收手可靠。
  • 把规划写进提示却不写进状态:复杂任务需要显式 todo / 状态机(LangGraph 一类),否则长对话里「计划」会被冲掉。

3. 上下文:窗口有限,策略才是能力

Agent 强不强,经常取决于 塞进上下文的东西是否刚好够用。常见策略:

  1. 按需检索:向量库 / 关键字搜仓库,而不是整库灌进 prompt。
  2. 工作区摘要:当前分支、最近 diff、相关文件列表先给一页「地图」,再按需 read_file。
  3. 会话记忆分层:短期(本轮 tool 结果)、中期(本任务的结论)、长期(用户偏好、项目约定)分开存,不要全挤在同一条 system 里。
  4. Skill / 说明书:把「本仓库怎么跑测试、怎么写 commit、评审看什么」写成可加载文档,需要时再注入——比每次口头重复稳定。

和「记忆」相关的务实结论:

  • 对话历史 不等于 可靠记忆;长会话要压缩或外部化。
  • 写进仓库的 AGENTS.md / Skill / 规则,往往比塞进某次聊天更可复用。
  • 敏感信息(密钥、token)不要进模型上下文;工具侧用环境变量与密钥管理。

4. MCP 与 Skill:协议层和流程层

4.1 MCP

MCP(Model Context Protocol) 把「工具 / 资源怎么接到模型宿主」标准化了:同一套客户端可以接 Git、浏览器、内部 HTTP、数据库只读接口等。对 Agent 开发者的意义是:

  • 少写一轮「每个 IDE 各接一遍」的胶水;
  • 权限与审计可以做在 MCP Server 边界上;
  • 换模型或换宿主时,工具面相对稳。

它不负责替你设计「何时调用、失败如何重试」——那仍是 Agent 循环与产品策略的事。

4.2 Skill

Skill(或同类「可复用流程说明书」)更偏 人写的、可版本管理的操作手册:触发条件、步骤、检查清单、输出格式。适合:

  • 代码评审口径统一;
  • 发布前检查;
  • 跨端迁移的质量门禁(见站内 MCP + Skill 一文)。

经验上:MCP 解决「能碰到什么」;Skill 解决「碰到之后按什么规矩做」。 二者叠在一起,Agent 才不至于每次从零猜项目习惯。


5. 技术选型怎么挑(够用即可)

需求 常见选择 备注
Python 快速原型 官方 SDK + 自写循环,或 LangChain 工具层 先跑通 3~5 个工具再上图编排
多步骤状态 / 分支 / 人工确认 LangGraph、自研状态机 显式节点比「全靠长 prompt」好调试
TypeScript / Node 全栈 Vercel AI SDK、OpenAI Agents SDK、自研 与前端同栈时排错成本低
IDE 内编码助手 Cursor Agent、Copilot Workspace 类 重点变成规则、MCP、仓库约定,而不是自建 UI
只要批处理脚本 不要 Agent cron + 确定性脚本更合适

Python 侧最小可运行思路(示意,非完整项目):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# 示意:一轮 tool-calling;真实项目还要错误分级、日志、鉴权
tools = [
{
"type": "function",
"function": {
"name": "read_file",
"description": "读取仓库内文本文件。path 为相对仓库根路径。",
"parameters": {
"type": "object",
"properties": {"path": {"type": "string"}},
"required": ["path"],
},
},
}
]

def run_agent(client, messages, max_steps=8):
for _ in range(max_steps):
resp = client.chat.completions.create(
model="gpt-4.1-mini", # 换成你实际用的模型 id
messages=messages,
tools=tools,
)
msg = resp.choices[0].message
if not msg.tool_calls:
return msg.content
messages.append(msg)
for tc in msg.tool_calls:
# 在这里做路径白名单、大小限制
payload = execute(tc.function.name, tc.function.arguments)
messages.append({
"role": "tool",
"tool_call_id": tc.id,
"content": payload[:8000],
})
return "已达步数上限,请缩小任务或提高权限边界后重试。"

选型原则只有一条:先让「一个工具 + 一步循环」在你自己的仓库里跑通,再加编排框架。反过来很容易变成框架文档驱动开发。


6. 评测与上线:比 demo 更要紧的部分

Agent demo 好看,不等于能进业务。上线前至少钉死:

  1. 任务集:准备 20~50 个真实小任务(修测试、改文案、查日志),固定输入,看成功率和平均步数。
  2. 回归:改 prompt / 换模型后重跑同一集合,避免「感觉变聪明了」其实是样本变简单了。
  3. 安全默认:写操作为准拒绝或二次确认;生产凭据不进工具默认环境;命令带 timeout。
  4. 可观测:每次 tool call 记名称、参数摘要、耗时、成败;出事故时能复盘「卡在第几步」。
  5. 人机边界:哪些步骤必须人点头(合并主分支、发版、付钱),写进产品而不是写进「模型应该懂」。

7. 和日常开发怎么叠

若你主要在 Cursor / 同类环境里用 Agent,工程化抓手通常是:

  • 仓库级规则与 Skill:构建命令、目录约定、禁止事项;
  • MCP:接内部文档、工单、浏览器、专用校验脚本;
  • 短反馈环:能本地 test / lint 的,就让 Agent 自己跑,少靠「我觉得编译过了」。

自研 Agent 服务时,则额外要做:会话存储、配额、多租户隔离、工具沙箱。那是另一篇文章的体量;本文把骨架定在 循环 + 上下文 + 协议/说明书 + 评测 四层,一般够支撑从 demo 走到可用。


8. 小结:动手时盯这几条

  • Agent = 带工具的推理循环,不是换皮聊天。
  • 工具 schema、结果裁剪、步数上限,比「再堆一个 Agent 框架」更能提升稳定性。
  • MCP 管连接面,Skill 管项目规矩;上下文策略决定上限。
  • 没有固定任务集和日志,就谈不上迭代模型或 prompt。

下一步若要加深,可以按方向拆:只做「编码 Agent 的仓库门禁」、或只做「LangGraph 状态机里的人工确认节点」。有具体仓库结构时,把工具列表和失败日志贴出来,比空谈框架版本有用得多。

MCP 与 Skill 驱动下的跨端代码转换与质量门禁

把 Android / iOS / 鸿蒙(HarmonyOS) 之间的工程迁移交给「大模型 + 工具」时,真正决定上限的往往不是单次对话写得多漂亮,而是:上下文从哪来、结果怎么验、每一轮提交怎么收口。本文从实践角度串一条链路:用 MCP 把仓库与外部能力接到 Agent 上,再用 Skill 把「怎么评转换质量、怎么总结变更、怎么对照需求、怎么看代码质量」固化成可重复执行的检查步骤。

说明:下文中的「转换」泛指在统一业务语义下,把一侧平台的实现(Kotlin/Swift/ArkTS 等)迁到另一侧或生成可对照骨架;不是宣称存在某种全自动、零成本的万能翻译器。MCP 与 Skill 解决的是流程与门禁,不是替代架构决策与人工验收。


1. 问题长什么样

典型诉求可以概括成四类:

方向 常见场景
Android → iOS 业务模块、网络层、存储、部分 UI 逻辑迁移到 Swift / SwiftUI
iOS → Android 对照实现 Kotlin / Jetpack,对齐生命周期与线程模型
与鸿蒙互转 ArkTS / ArkUI 与双端对齐能力差异(线程、权限、分布式、声明式 UI)
多向迭代 同一需求在三端分支并行改,需要统一的「需求—实现—差异」视图

纯靠聊天窗口贴代码,很快会遇到:上下文截断、无法读全仓库、无法跑构建与静态检查、无法稳定对比两次提交的差异。这就是 MCP 要接进来的原因。


2. MCP 在这条链路里干什么

MCP(Model Context Protocol) 做的是:让模型通过标准协议调用「工具」和拉取「资源」,而不是把整台电脑或整库文件糊进提示词。

在跨端迁移/转换场景里,常见有价值的 MCP 能力包括(按优先级大致排序):

  1. 代码与版本:读文件、搜索符号、git diff / git log、关联 issue / 需求文档(若你们有对应 MCP 或 HTTP 封装)。
  2. 构建与检查:触发 Gradle / xcodebuild / hvigor(鸿蒙)的非交互命令,采集编译错误与警告(需沙箱与安全策略)。
  3. 静态分析:对接 linter、格式化结果、甚至你们内部的二进制接口规范检查脚本。
  4. 知识库:设计文档、接口契约、历史 CR 结论——用 resource 或检索类工具喂给模型当约束,而不是当闲聊材料。

一张很粗的协作关系如下:

Agent(IDE / CLI) 对话与计划 MCP 服务 Git / 文件 构建与日志 Lint / 测试 需求与文档 工程仓库 Android / iOS / Harmony 模块

要点:MCP 负责「能持续拿到真实状态」;模型负责在约束下改代码。没有 MCP,跨端转换很容易变成「语法像、跑不通」的演示。

项目实践里 MCP 真正帮上忙的一块

在自己项目里跑下来,MCP 带来的提效很实在的一点,是支撑 大块功能在端之间的直接互转:网络、状态、一条完整业务链路里的多个类/模块,在接好仓库与构建/日志之后,Agent 能按「功能点」连续改,而不是只在聊天里贴片段。这和「整仓库一键翻译」不是一回事,但已经能覆盖不少成块迁移的工作。

转换落地之后,仍然需要人按需求自己多走几遍:主路径、边界条件、各端差异(权限、后台、埋点)往往要手动点一点才暴露。这里不必讳言——人工走查仍是验收的一环。差别在于:一旦发现问题,把报错、堆栈、复现步骤丢回给 AI,在 MCP 能读到工程上下文的前提下,修一轮的成本明显低于从零手改。整体仍是:大功能先转过去 → 人按需求验收 → 卡点再交给 AI 迭代,提效很多,但预期是「加速器」,不是「免验收」。


3. 转换工作流建议(可落地的一版)

下面是一条在团队里较容易推广的最小闭环,可按你们 CI 成熟度裁剪。

对齐需求与范围 建立对照表:模块/接口/平台差异 分支策略:按端或按业务垂直切 大功能点互转 + 本地构建 人按需求走查多遍 把现象与日志交给 AI 修复 门禁:Skill 清单跑一遍 PR:说明对照与风险 发现问题 修复后回到转换 通过 不通过 通过
  1. 对齐需求与范围:哪些类/模块要迁、哪些只做适配层、哪些必须行为一致(加密、存储、埋点)。
  2. 对照表:把「Android 类 / iOS 类型 / ArkTS 组件」映射到同一张表,避免三端各写各的命名与语义漂移。
  3. 分支:要么「一需求一分支三端子目录」,要么「按端拆分支但共享契约文档」——关键是 diff 可读、review 可追责。
  4. 大功能点转换 + 构建优先:先争取「能编过、主链路能跑」;报错与日志进 Agent 上下文(MCP),便于迭代大块改动而不是零散粘贴。
  5. 人工按需求走查:对照验收条目多点几遍;出问题再 提醒 AI 修(复现步骤 + 日志/截图),形成短闭环,而不是指望一次生成就结项。
  6. 门禁再走 PR:下文 Skill 部分把这一步拆成可执行检查项。

4. 用 Skill 做「质量门禁」:评什么、怎么评

Skill 在这里不是替你做代码审查的人,而是把「每次该怎么审」写成稳定流程,让 Agent 和人类用同一套清单。可以与 .cursor/rules 分工:规则偏常驻约束,Skill 偏「进入迁移任务时按需加载」。

下面四类,对应你提到的诉求。

4.1 评估「转换质量」(对照与语义)

建议在 Skill 里写清输入与输出:

  • 输入:源端关键文件路径、目标端对应路径、需求编号或用户故事摘要。
  • 输出:一张结构化表,至少包含:
    • API / 行为对照:异步模型(Kotlin 协程 vs Swift async vs Promise)、主线程约束、错误类型是否可对应。
    • 平台差异显式声明:例如 Keychain vs Keystore vs 鸿蒙安全存储、推送与后台任务差异。
    • 已知妥协:哪些为赶进度采用临时方案,必须带 TODO(@owner, deadline)。

转换质量不是「看起来像」,而是「在约束下可维护且可验证」。

4.2 总结「每次提交的变更内容」

与其让模型自由发挥写 PR 描述,不如在 Skill 里规定:

  • 固定调用 git diff / git show(通过 MCP)得到事实;
  • 再按模板归纳:文件级摘要 → 行为变化 → 风险点 → 测试建议;
  • 禁止把「推测的业务意图」写进摘要当事实(除非文档里有依据)。

这样每一轮提交都有可比对、可审计的变更说明,也方便后面做需求完成度对照。

4.3 评估「需求完成度」

把需求拆成可勾选条目(验收标准),在 Skill 中要求:

  • 每条对应 commit 或 PR 中的证据(实现位置、测试用例、或文档更新);
  • 未完成项必须标 阻塞原因(依赖、接口未就绪、平台能力缺失)。

没有结构化条目,「差不多做完了」无法复盘。

4.4 评估「提交代码的质量」

建议在 Skill 里分三层,由浅入深:

层级 内容示例
机械层 格式化、命名、明显死代码、错误处理分支是否完整
工程层 日志是否泄露敏感信息、并发与生命周期是否匹配平台习惯
语义层 是否与对照表一致、边界条件是否与源端测试意图对齐

静态检查能覆盖机械层与部分工程层;语义层需要测试或人工 spot check。Skill 里应写明:哪些必须跑命令、哪些允许仅人工。


5. 示例:Skill 里可以长什么样(片段)

下面是一段示意性的 Markdown 结构,便于你落到仓库里的 SKILL.md(真实项目请补全 name、description 与触发条件)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
---
name: cross-platform-migration-review
description: Android/iOS/鸿蒙互迁时的对照审查与提交摘要
---

## 何时使用
用户提到跨端迁移、对照实现、ArkTS/Kotlin/Swift 同步修改时加载本 Skill。

## 步骤
1. 用 MCP 读取当前分支相对 main 的 diff 与最近 N 次提交信息。
2. 对照 `docs/platform-mapping.md`(若存在)检查涉及模块是否登记。
3. 按「转换质量 / 变更摘要 / 需求条目 / 代码质量」四节输出,缺信息则列出待补充问题。
4. 若涉及鸿蒙,显式检查线程与权限相关 API 是否与文档一致。

## 输出模板(节选)
### 变更摘要(基于 diff)
- 范围:...
- 行为变化:...
- 风险:...

### 需求完成度
| 条目 | 状态 | 证据 |

实际仓库里你会把路径、分支名、文档名换成自己的约定。


6. 局限与诚实边界

  • MCP 不是魔法:没有构建环境、没有测试、没有清晰需求,再好的协议也只能产出「更像代码的文本」。
  • 三端互转在工程上常卡在 能力不对等(系统服务、商店政策、声明式 UI 数据流),Skill 应要求把这些写进「已知妥协」,而不是一笔带过。
  • 安全:能执行命令的 MCP 必须限权、审计;不要把生产密钥放进可被模型读取的资源。

7. 小结

  • MCP 解决的是:让 Agent 稳定读仓库、跑检查、对齐事实,跨端转换才有可持续的闭环。
  • Skill 解决的是:把 转换质量、变更摘要、需求完成度、代码质量 变成可重复执行的评审步骤,减少「同一类问题每次重新口头讲一遍」。

若你已经在用 Cursor / Claude Code 一类工具,优先落地的往往是:一个最小 MCP 集合(git + 终端或 CI 日志)+ 一个迁移审查 Skill;再逐步把需求条目与对照表接进来。和自己在项目里的做法一样:大功能点先互转、人按需求走查、问题再丢给 AI,比一上来追求「全自动三端零走查」更实在,也更容易稳定提效。


本文为工程流程向说明,具体工具链与 MCP Server 名称以各厂商文档为准;实施时请结合团队安全与合规要求。