☰
AI Agent开发指南:Prompt、RAG、Function Calling、MCP四大核心技术配置实战
2026/9/29 3:45:20 网站建设 项目流程

1. 从一次 Agent 跑不通说起:四大技术到底卡在哪

AI Agent 开发入门最让人抓狂的地方,不是概念听不懂,而是每个概念都懂一点,拼起来就跑不通。Prompt 写得挺像回事,RAG 也把向量库建起来了,Function Calling 的 JSON Schema 照着文档抄了,MCP 的 Server 也启动了,结果一联调:模型不调用工具、检索回来的片段答非所问、MCP 客户端连不上 Server、报错信息还全是英文堆栈。

这篇就聚焦一件事:把 Prompt、RAG、Function Calling、MCP 这四块在工程里的接入位置和配置骨架讲清楚,让你能复制粘贴出一套最小可跑的 Agent 基础链路。适合刚接触 Agent 开发、手里有一个模型 API Key、想快速跑通第一个能调用工具的 Agent 的开发者。全文以配置文件为主线,settings.json、config.toml、.env 三种形态都会给到,每一步都配验证动作,跑不通就对照第 5 节的排查表。

先说清楚四者在链路里的分工,后面配置才不会乱:

技术在 Agent 里的角色典型配置文件验证方式
Prompt大脑的指令层prompts/system.md单轮对话看输出格式
RAG外挂知识库config.toml检索片段命中率
Function Calling手脚,调外部工具tools.json模型返回 tool_calls
MCP工具接入的标准化协议mcp.jsonServer 握手成功

2. 前置准备:TaoToken 接入与项目骨架

2.1 为什么用统一网关而不是直连各家

Agent 开发阶段最烦的是模型换来换去:今天用这个测 Prompt,明天换那个测 Function Calling,每换一家就要改 base_url、改鉴权头、改返回解析。用 TaoToken 这类统一网关的好处是,OpenAI 兼容协议一套走到底,切换模型只改一个 model 字段。官网在 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 入口是 https://taotoken.net/api ,注意 API 地址不带 UTM 参数,配置里填这个就行。

2.2 拿 Key 与目录结构

登录后进控制台创建 API Key,入口在 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite ,Key 的管理页在 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite 。Key 只显示一次,复制到本地 .env,别提交到 Git。

项目骨架建议这样分,四块技术各占一个目录,互不干扰:

agent-demo/ ├── .env # 密钥,不进版本库 ├── settings.json # 模型与运行参数 ├── config.toml # RAG 检索参数 ├── tools.json # Function Calling 声明 ├── mcp.json # MCP Server 注册 ├── prompts/ │ └── system.md # 系统提示词 └── src/ ├── llm.py # 统一模型调用 ├── rag.py # 检索增强 ├── tools.py # 函数执行 └── agent.py # 主循环

2.3 .env 与 settings.json 骨架

.env 只放密钥和网关地址:

TAOTOKEN_API_KEY=sk-你的key TAOTOKEN_BASE_URL=https://taotoken.net/api

settings.json 放模型与运行参数,这是整个 Agent 的入口配置:

{ "model": "gpt-4o-mini", "base_url": "https://taotoken.net/api", "temperature": 0.2, "max_tokens": 2048, "timeout": 60, "max_tool_rounds": 5, "system_prompt_file": "prompts/system.md" }

temperature 设 0.2 是因为 Agent 场景要的是稳定复现,不是创意写作;max_tool_rounds 限制工具调用轮数,防止模型陷入无限调用。这两个参数后面排查死循环时会反复用到。

3. Prompt 与 RAG 的配置骨架

3.1 系统提示词写成文件而不是硬编码

Prompt 是 Agent 的指令层,最容易犯的错是把它塞在代码字符串里,改一次要动代码。写成 prompts/system.md,结构按「角色 + 任务 + 约束 + 输出格式」四段来:

# 角色 你是一个数据查询助手,负责根据用户问题调用工具或检索知识库。 # 任务 1. 判断问题是否需要外部数据,需要则调用对应工具 2. 不需要工具时,基于检索片段回答 3. 无法确定时,明确说"信息不足",不要编造 # 约束 - 只使用工具返回的真实数据,禁止臆测 - 引用知识库内容时标注来源片段编号 # 输出格式 - 工具调用:直接返回 function call,不要额外解释 - 文本回答:先给结论,再给依据

约束段里「禁止臆测」和「标注来源」这两条,是压幻觉最有效的两句话,比在代码里做后处理省事得多。

3.2 RAG 的 config.toml

RAG 的接入位置在「模型调用之前」:用户问题先过检索器,命中的片段拼进 Prompt 再送给模型。config.toml 把检索参数集中管理:

[embedding] model = "text-embedding-3-small" base_url = "https://taotoken.net/api" batch_size = 32 [retrieval] top_k = 4 score_threshold = 0.35 chunk_size = 500 chunk_overlap = 80 [store] type = "local" path = "./data/index"

top_k 给 4 是经验值:太少召回不全,太多挤占上下文还引入噪声。score_threshold 是过滤低质量片段的闸门,低于 0.35 的直接丢,宁可少给也别给错。chunk_overlap 设 80 是为了缓解切片切断语义的问题,让相邻块有重叠。

3.3 检索与拼装的代码骨架

import tomllib from openai import OpenAI with open("config.toml", "rb") as f: cfg = tomllib.load(f) client = OpenAI( api_key=os.environ["TAOTOKEN_API_KEY"], base_url=os.environ["TAOTOKEN_BASE_URL"], ) def retrieve(query: str, top_k: int = 4): vec = embed(query) hits = index.search(vec, top_k) return [h for h in hits if h.score >= cfg["retrieval"]["score_threshold"]] def build_prompt(query: str, hits: list) -> str: context = "\n".join(f"[{i}] {h.text}" for i, h in enumerate(hits)) return f"参考资料:\n{context}\n\n用户问题:{query}"

注意 build_prompt 里给每个片段编了号,配合系统提示词里的「标注来源片段编号」,模型回答时就能带上 [0][2] 这类引用,方便你核对它到底有没有瞎编。

4. Function Calling 与 MCP 的配置骨架

4.1 tools.json 声明工具

Function Calling 的接入位置在「模型返回之后」:模型决定调哪个函数、传什么参数,你的代码负责真正执行。tools.json 用标准 JSON Schema 声明:

{ "tools": [ { "type": "function", "function": { "name": "get_weather", "description": "查询指定城市的实时天气", "parameters": { "type": "object", "properties": { "city": { "type": "string", "description": "城市名,如 杭州" }, "unit": { "type": "string", "enum": ["celsius", "fahrenheit"] } }, "required": ["city"] } } } ] }

description 写得越具体,模型选错函数的概率越低。enum 限定取值范围,能挡掉一批参数格式错误。

4.2 工具执行与主循环

import json with open("tools.json") as f: TOOLS = json.load(f)["tools"] def run_agent(messages: list): for _ in range(settings["max_tool_rounds"]): resp = client.chat.completions.create( model=settings["model"], messages=messages, tools=TOOLS, temperature=settings["temperature"], ) msg = resp.choices[0].message messages.append(msg) if not msg.tool_calls: return msg.content for call in msg.tool_calls: args = json.loads(call.function.arguments) result = dispatch(call.function.name, args) messages.append({ "role": "tool", "tool_call_id": call.id, "content": json.dumps(result, ensure_ascii=False), }) return "达到最大工具调用轮数,已中止"

这个循环就是 ReAct 范式的工程实现:模型思考、发起调用、拿到观察结果、再思考。max_tool_rounds 是安全阀,防止模型反复调同一个工具停不下来。

4.3 mcp.json 注册 MCP Server

MCP 解决的是工具接入的标准化问题:不用每接一个工具就手写一份 JSON Schema,Server 自己声明能力,客户端自动发现。mcp.json 注册 Server:

{ "mcpServers": { "filesystem": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "./data"], "env": {} } } }

MCP 的接入位置在「工具层之下」:它把 Function Calling 的声明和执行都标准化了,你的 Agent 主循环可以不变,工具来源从手写 tools.json 换成 MCP Server 动态拉取。想深入看协议细节和更多 Server 示例,可以翻接入文档 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite 。

5. 验证请求与常见报错排查

5.1 三步验证法

第一步,验证模型连通。用模型对话页面 https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_content=models&utm_campaign=rewrite 直接发一句「返回 JSON:{"ok":true}」,确认 Key 和 base_url 没问题。

第二步,验证 Function Calling。发「杭州天气怎么样」,看返回里有没有 tool_calls 字段:

resp = client.chat.completions.create( model="gpt-4o-mini", messages=[{"role": "user", "content": "杭州天气怎么样"}], tools=TOOLS, ) print(resp.choices[0].message.tool_calls)

第三步,验证 RAG。问一个只有你知识库里有答案的问题,看回答里有没有片段编号引用。

5.2 常见报错对照表

报错现象大概率原因处理动作
401 UnauthorizedKey 没读到或带空格检查 .env 是否被加载
模型不返回 tool_callstools 没传或 description 太模糊打印请求体确认 tools 字段
参数解析失败arguments 不是合法 JSON加 try 兜底并回灌错误信息
RAG 答非所问top_k 太大或阈值太低调小 top_k,调高 threshold
MCP 连接超时command 路径不对手动执行 command 验证
循环停不下来工具返回空导致模型重试设 max_tool_rounds 上限

其中「模型不返回 tool_calls」最常见,八成是 tools 参数没传进去,或者 description 写成了「查询天气」这种没有信息量的描述。改成「查询指定城市的实时天气,返回温度和天气状况」立刻就好。

5.3 长期编码场景的配置建议

如果你是要把 Agent 接到日常编码或长任务里,单次调用模式不够用,需要能持续跑、能记住上下文的方案。这类场景可以看 Coding Plan https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite ,配置思路和上面一致,只是把 max_tool_rounds 放宽、加上会话持久化。Claude Code 这类工具的接入方式在 https://taotoken.net/claudecode?utm_source=taotoken_aicg_blog_end&utm_content=claudecode&utm_campaign=rewrite 有说明,本质还是同一套 base_url + Key 的配置。

6. 把四块拼成一条能跑的链路

回到开头那个跑不通的问题:四块技术各自的配置骨架其实都不复杂,难的是接入位置要对。Prompt 在最上层定规则,RAG 在模型调用前做检索拼装,Function Calling 在模型返回后做执行回灌,MCP 在工具层做标准化。顺序错了,就会出现「检索结果没进 Prompt」「工具返回没回灌给模型」这类看起来像模型笨、实际是链路断的问题。

建议的推进顺序是:先用 settings.json 跑通单轮对话,再加 tools.json 验证 Function Calling,然后接 config.toml 上 RAG,最后用 mcp.json 把工具来源标准化。每加一块就跑一次第 5 节的验证动作,别四块一起上再联调,那样报错根本定位不到是哪一层。这套骨架跑通之后,换模型、加工具、扩知识库都只是改配置的事,主循环不用动。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询