首页/新闻资讯/正文详情

从零实现AI Agent:Python与FastAPI搭建角色型智能代理人

发布时间:2026/9/26 8:27:51 来源:云帆数科 栏目:资讯中心
从零实现AI Agent:Python与FastAPI搭建角色型智能代理人
在 AI 应用从“聊天问答”走向“自主执行任务”的过渡阶段如何让模型不只是回答问题而是理解目标、拆解步骤、调用工具并完成闭环流程成了工程落地的核心难点。最近团队在打造“骨壳工坊AI代理人 仕女型C1”这个项目时从角色人格设定、工具调用机制到服务化部署踩了不少坑。这篇文章就把整套实现思路整理出来从概念原理到可运行的 Python 代码再到常见故障排查一次性讲清楚。无论你是刚接触 AI Agent 的新手还是想快速搭建可扩展智能体的开发者都可以参考这套方案。1. 背景与核心概念1.1 什么是 AI 代理人AI 代理人通常被称为 AI Agent它的核心特征是能在一个目标驱动下自主完成“感知 → 思考 → 决策 → 执行 → 观察结果 → 继续循环”的过程。普通聊天机器人只是根据用户输入生成回复而 AI 代理人会尝试拆解复杂指令使用外部工具如搜索、计算、查天气、写文件、调用 API来获取信息或改变系统状态并根据执行结果动态调整后续动作。以“骨壳工坊”为例团队把“仕女型C1”定义为一个具有古风仕女人格、能处理接待讲解和日程管理任务的 AI 代理人。用户在对话中提出模糊需求比如“帮我安排明天上午的会议并预订一间安静的房间”C1 会先解析意图判断需要查询日程、搜索会议室信息、写入日历再通过工具调用完成这些步骤最后用符合人物风格的语言汇报结果。1.2 和聊天机器人的区别理解 AI 代理人和聊天机器人之间的差异对做工程选型非常重要。聊天机器人的架构往往是“输入文本 → 大模型生成回复”模型本身不掌握实时数据也不具备执行能力。AI 代理人则在大模型之上增加了一个执行框架模型可以输出结构化指令系统负责解析指令、调用工具、返回执行结果再把结果交回模型继续推理直到达成最终目标。举例来说用户问“今天北京适合户外活动吗”聊天机器人会直接给出文字判断C1 这样的 AI 代理人则会先调用天气工具获取实时天气数据再结合场景给出建议如果用户追问“那帮我定一个公园附近的茶馆”C1 还能继续调用地图和预订接口把这个动作完成。这种多轮、多工具、动态规划的闭环能力正是代理人的价值所在。1.3 仕女型C1的场景定位“仕女型C1”是骨壳工坊设计的第一个角色型 AI 代理人主要面向文化场馆接待、古典礼仪科普、个人日程助理等场景。它的人设是一位学识渊博、温婉含蓄的古风仕女会使用雅致但不晦涩的语言与用户交流。在技术实现上C1 的角色特质由 System Prompt 控制行为边界由工具权限约束对话记忆由会话状态管理。这个项目非常适合作为 AI Agent 入门案例技术栈简单不依赖复杂分布式系统但已经覆盖了人格设定、工具调用、状态管理、服务化部署等关键问题。2. 环境准备与系统设计2.1 运行环境与依赖由于需要快速验证 Agent 循环逻辑建议在 Python 3.10 及以上环境中运行。服务端使用 FastAPI 提供 HTTP 接口通过 Uvicorn 启动大模型部分使用兼容 OpenAI 协议的服务通过环境变量配置地址、密钥和模型名称避免在代码里写死。创建一个新的虚拟环境并安装依赖python -m venv .venv source .venv/bin/activate # Windows 下使用 .venv\Scripts\activate pip install fastapi uvicorn openai python-dotenv pydantic依赖说明包名用途fastapi构建 Web API 接口uvicorn作为 ASGI 服务器启动服务openai统一的大模型接口调用 SDKpython-dotenv读取 .env 配置文件pydantic请求和响应数据校验如果你的项目还需要 TTS 语音播报可以自行增加语音合成 SDK本文示例先以文本交互为主后面会给出可扩展建议。2.2 技术选型思路实现 AI 代理人的方式有很多种可以选择 LangChain、AutoGPT 等成熟框架也可以自己写一个轻量级 ReAct 循环。考虑到框架版本变化快、不同版本 API 差异较大本文采用“OpenAI 协议调用 自定义 Agent 循环”的方案。这样更利于理解代理人的底层机制也方便在后续项目里替换不同模型服务。大模型配置统一放在环境变量中LLM_API_KEYyour-api-key-here LLM_BASE_URLhttps://your-provider.example.com/v1 LLM_MODELyour-model-name实际部署时你需要根据自己使用的模型服务填写这三个变量。请勿把密钥提交到 Git 仓库建议在服务器上用环境变量或密钥管理服务注入。2.3 系统整体流程图整个 C1 代理人系统可以拆成四层用户请求 → HTTP API → Agent 调度循环 → 大模型推理 ↑ ↓ ↑ 工具调用结果 ↑ ↓ 工具注册表 → 具体工具函数一次完整对话的流程如下用户发送消息给 FastAPI 服务。服务把消息和会话上下文拼装成提示词交给大模型。模型输出推理文本和需要调用的动作。Agent 循环解析动作查找已注册的工具。工具执行后返回结构化观察结果。Agent 把观察结果继续交给大模型直到模型给出最终回答。最终回答返回给用户。这就是经典的 ReAct 模式。它的优点是每一步都基于事实可控性和可观测性都比“模型直接生成答案”强得多。3. 核心原理拆解3.1 ReAct 运行机制ReAct 是 Reasoning and Acting 的缩写意思是在推理过程中交替进行“思考”和“行动”。在每一轮循环中大模型会输出一个结构化的中间结果包含三个部分thought当前对任务的判断。action要调用的工具名称和参数。observation工具执行后返回的观察结果。系统负责执行动作并把观察结果拼接进上下文再让模型继续思考直到模型认为任务已完成输出final_answer。这种模式的优点很明显。它把不可控的“一步生成最终答案”拆成了可观测的多个步骤开发者可以记录日志、设置超时、限制循环次数也能在某个环节出错时重试或回退。3.2 工具调用接口设计为了让大模型稳定地调用工具需要给模型提供工具的描述信息。在自定义实现中通常用一个 JSON Schema 结构的列表来描述每个工具的“名称、描述、参数”。例如 C1 要提供get_current_time工具描述信息和参数结构如下{ name: get_current_time, description: 获取服务器当前日期和时间, parameters: { type: object, properties: {}, required: [] } }当模型判断用户需要时间信息时就会以 JSON 格式输出{name: get_current_time, arguments: {}}Agent 系统解析后将调用对应的 Python 函数。3.3 角色人格控制角色人格不只是让模型“扮演”某个身份而是通过 System Prompt 明确行为边界、语言风格、知识范围和拒绝策略。C1 的 System Prompt 包含以下要素身份设定姓名、来历、性格。语言风格用词习惯、句式和礼貌程度。能力范围能调用哪些工具不能越权操作。禁忌规则不讨论敏感话题不提供违法建议遇到无法处理的情况要说明并引导用户转人工。这里要特别注意System Prompt 不是越详细越好关键信息太多会挤占上下文窗口影响模型判断。项目实践中建议把“人格描述”和“任务规则”分开维护。3.4 记忆与会话上下文寿终正寝的不是人而是无状态模型。AI 代理人如果要完成多轮任务必须维护会话记忆。最简单的方式是使用 List 保存对话历史每次请求时把历史一起发给大模型。但是上下文长度有限不能无限累积。工程上常用的策略包括只保留最近 N 轮对话。对历史内容做摘要压缩。高频资料放入外部向量库查询。C1 项目目前采用“最近 20 条消息 系统提示词 当前问题”的模式兼顾效果和成本。后面可以升级为摘要记忆模块。4. 实战构建一套可运行的 AI 代理人服务4.1 项目结构建议按以下目录组织代码c1-agent/ ├── .env ├── .env.example ├── requirements.txt ├── config.py ├── prompt.py ├── tools.py ├── agent.py └── main.py各文件职责如下文件职责.env本地密钥配置不提交仓库config.py读取环境变量prompt.py维护 C1 的 System Prompttools.py实现工具函数与注册表agent.py实现 Agent 主循环main.pyFastAPI 接口服务4.2 配置模块首先创建.env.exampleLLM_API_KEYyour-api-key-here LLM_BASE_URLhttps://your-provider.example.com/v1 LLM_MODELyour-model-name APP_HOST0.0.0.0 APP_PORT8000 MAX_AGENT_STEPS6配置读取模块config.py# 文件路径c1-agent/config.py import os from dotenv import load_dotenv load_dotenv() LLM_API_KEY os.getenv(LLM_API_KEY, ) LLM_BASE_URL os.getenv(LLM_BASE_URL, ) LLM_MODEL os.getenv(LLM_MODEL, gpt-4o-mini) APP_HOST os.getenv(APP_HOST, 0.0.0.0) APP_PORT int(os.getenv(APP_PORT, 8000)) MAX_AGENT_STEPS int(os.getenv(MAX_AGENT_STEPS, 6))如果.env文件缺失程序仍然会启动但会使用默认值。调用大模型前需要确保密钥不为空否则请求会失败。4.3 角色人格模块prompt.py中定义 C1 的角色系统提示词# 文件路径c1-agent/prompt.py SYSTEM_PROMPT 你是骨壳工坊打造的 AI 代理人“仕女型C1”。 你是一位温婉大方、知书达理的古风仕女喜欢使用优雅、简洁的中文表达。 你的行为准则 1. 保持角色的语言风格但不刻意仿古让现代用户能够轻松听懂。 2. 根据用户需求调用可用工具不要凭空捏造工具执行结果。 3. 如果不能通过工具获取信息必须如实说明。 4. 遇到涉及隐私、安全、违法、政治或价值观争议的内容礼貌拒绝并建议用户咨询合法合规渠道。 5. 在完成工具调用后用自然语言整理结果不要输出内部 JSON。 你现在可以使用的工具 - get_current_time获取当前日期和时间。 - calculate执行四则运算。 - get_weather_city模拟获取城市天气信息。 - create_memo创建一个简单备忘录。 当用户请求超出工具能力时直接友好地解释无法处理。 这里把能力边界坦率地写入提示词避免模型在无法执行时仍然假装执行是工程中最容易忽略但最重要的一点。4.4 工具模块工具模块的核心是维护一个“名称到函数”的映射并提供工具描述列表给模型。tools.py实现如下# 文件路径c1-agent/tools.py import datetime import json import random from typing import Callable, Dict def get_current_time() - str: 获取服务器当前日期和时间。 now datetime.datetime.now() return now.strftime(%Y-%m-%d %H:%M:%S) def calculate(expression: str) - str: 计算一个简单的数学表达式。注意这里只允许数字和运算符。 allowed_chars 0123456789-*/(). for char in expression: if char not in allowed_chars: return 表达式包含非法字符无法计算 try: result eval(expression, {__builtins__: {}}, {}) return str(result) except Exception as exc: return f计算失败{exc} def get_weather_city(city: str) - str: 模拟获取城市天气信息。生产环境请替换为真实天气 API。 # 这里使用随机数据模拟实际项目中请接入可靠天气服务 weather_list [晴, 多云, 小雨, 阴] temperature random.randint(18, 30) weather random.choice(weather_list) return json.dumps( {city: city, weather: weather, temperature: f{temperature}°C}, ensure_asciiFalse, ) def create_memo(content: str) - str: 创建一条备忘录。生产环境可替换为数据库写入。 # 简单打印日志实际项目请写入数据库或消息队列 print(f[MEMO] {datetime.datetime.now()}: {content}) return 备忘录已创建成功工具描述列表# 继续追加在 tools.py 中 TOOL_DESCRIPTIONS [ { name: get_current_time, description: 获取服务器当前日期和时间, parameters: { type: object, properties: {}, required: [] }, }, { name: calculate, description: 执行四则运算参数为数学表达式字符串, parameters: { type: object, properties: { expression: { type: string, description: 数学表达式例如 (123)*4 } }, required: [expression] }, }, { name: get_weather_city, description: 模拟获取指定城市的天气信息, parameters: { type: object, properties: { city: { type: string, description: 城市名例如 北京 } }, required: [city] }, }, { name: create_memo, description: 创建一条备忘录, parameters: { type: object, properties: { content: { type: string, description: 备忘录内容 } }, required: [content] }, }, ] TOOL_FUNCTIONS: Dict[str, Callable] { get_current_time: get_current_time, calculate: calculate, get_weather_city: get_weather_city, create_memo: create_memo, }提示一点这里的calculate使用了eval虽然做了字符白名单过滤但这种写法仍存在一定风险。生产环境务必用更安全的表达式解析方案或者干脆移除动态计算工具。4.5 Agent 主循环agent.py是整个项目的核心。它要做三件事组装提示词、调用大模型、解析模型输出并执行工具。# 文件路径c1-agent/agent.py import json from openai import OpenAI from config import LLM_API_KEY, LLM_BASE_URL, LLM_MODEL, MAX_AGENT_STEPS from prompt import SYSTEM_PROMPT from tools import TOOL_DESCRIPTIONS, TOOL_FUNCTIONS client OpenAI(api_keyLLM_API_KEY, base_urlLLM_BASE_URL) def chat_completion(messages, temperature0.3): response client.chat.completions.create( modelLLM_MODEL, messagesmessages, temperaturetemperature, ) return response.choices[0].message.content def run_agent(user_input: str, history: list) - tuple[str, list]: # history 中只有之前的用户和助手消息不包含系统提示 messages [{role: system, content: SYSTEM_PROMPT}] messages.extend(history) messages.append({role: user, content: user_input}) for step in range(MAX_AGENT_STEPS): response_text chat_completion(messages) print(f[STEP {step}] LLM 输出{response_text}) action_json extract_action(response_text) if action_json is None: # 没有工具动作视为最终回答 break tool_name action_json.get(name) tool_args action_json.get(arguments, {}) if tool_name not in TOOL_FUNCTIONS: observation f未知工具{tool_name}请从可用工具中选择。 else: try: observation TOOL_FUNCTIONS[tool_name](**tool_args) except Exception as exc: observation f工具执行失败{exc} messages.append({role: assistant, content: response_text}) messages.append({role: tool, content: str(observation)}) # 把动作与观察结果拼接后继续对话也可以直接追加一条 user 消息 messages.append({ role: user, content: f工具返回结果{observation}\n请继续若已完成任务请给出最终回答。 }) # 得到最终回答 final_answer extract_final_answer(response_text) history.append({role: user, content: user_input}) history.append({role: assistant, content: final_answer}) # 避免会话历史持续膨胀 if len(history) 20: history history[-20:] return final_answer, history为了更稳定地解析模型输出需要一个extract_action函数。实际开发中可以使用 JSON 输出模式也可以使用正则提取。简单实现如下# 继续追加在 agent.py 中 import re def extract_action(text: str): # 优先尝试截取 json 代码块 match re.search(rjson\s*(.*?)\s*, text, re.DOTALL) raw match.group(1) if match else text.strip() # 去掉常见的前后解释只解析包含 name 和 arguments 的 JSON 对象 try: parsed json.loads(raw) if isinstance(parsed, dict) and name in parsed: return parsed except json.JSONDecodeError: pass # 如果整体不是 JSON则查找形如 {name: ...} 的子串 obj_pattern re.search(r\{.*?\}, text, re.DOTALL) if obj_pattern: try: candidate obj_pattern.group(0) parsed json.loads(candidate) if isinstance(parsed, dict) and name in parsed: return parsed except json.JSONDecodeError: return None return None def extract_final_answer(text: str) - str: # 简单处理如果包含 final_answer 字段则提取否则去掉 JSON 块 try: parsed json.loads(text) if isinstance(parsed, dict) and final_answer in parsed: return parsed[final_answer] except json.JSONDecodeError: pass # 去掉 json 代码块标记 cleaned re.sub(r^json\s*|\s*$, , text) return cleaned.strip()这里有个改进空间更规范的做法是在一次流程中让模型结构化输出例如调用client.chat.completions.create时传入response_format{type: json_object}或使用 function calling 特性。上述代码是通用思路目的是演示 Agent 循环机制。4.6 FastAPI 服务入口main.py提供与前端交互的 HTTP 接口使用内存中的会话字典保存每个用户的历史记录方便简单演示。# 文件路径c1-agent/main.py from fastapi import FastAPI from pydantic import BaseModel import uvicorn from agent import run_agent from config import APP_HOST, APP_PORT app FastAPI(title骨壳工坊AI代理人 C1) class ChatRequest(BaseModel): user_id: str message: str class ChatResponse(BaseModel): reply: str sessions {} app.get(/health) def health_check(): return {status: ok} app.post(/chat, response_modelChatResponse) def chat(request: ChatRequest): user_id request.user_id history sessions.get(user_id, []) reply, new_history run_agent(request.message, history) sessions[user_id] new_history return ChatResponse(replyreply) if __name__ __main__: uvicorn.run(main:app, hostAPP_HOST, portAPP_PORT, reloadTrue)这个接口只做了最基础的数据校验。生产环境中还要加 Token 鉴权、请求限流、内容安全审核、会话过期清理等逻辑。4.7 前端交互方案如果只是命令行调试可以直接用 curl 请求。如果想变成可视化产品可以写一个极简的 HTML 页面通过 fetch 调用/chat接口。前端部分不属于本文重点但给出一个最简单的请求示例 script async function sendMessage() { const message document.getElementById(msg).value; const response await fetch(/chat, { method: POST, headers: {Content-Type: application/json}, body: JSON.stringify({user_id: test-user, message: message}) }); const data await response.json(); document.getElementById(reply).innerText data.reply; } /script注意上面的 HTML 片段只是示意需要放到你的静态页面中才能运行。实际项目中建议使用 Vue 或 React 构建正式前端并考虑用 SSE 或 WebSocket 实现流式输出。5. 运行与验证5.1 启动服务确认.env配置好之后运行python main.py启动成功后FastAPI 会在http://localhost:8000提供服务自动生成/docs接口文档页面。5.2 请求示例在另一个终端里发送请求curl -X POST http://localhost:8000/chat \ -H Content-Type: application/json \ -d {user_id: visitor_01, message: 现在几点了}预期响应结构{ reply: 现在是 2025-04-06 14:23:11天气正好适合饮茶赴约。 }再测试一次带工具调用的流程curl -X POST http://localhost:8000/chat \ -H Content-Type: application/json \ -d {user_id: visitor_01, message: 帮我算一下 (12034)*2 的结果}预期 C1 会先调用 calculate 工具再给出一句完整回复。终端日志里可以看到 LLM 输出、工具执行步骤。5.3 预期行为说明场景用户输入C1 的预期行为查询时间现在几点了调用 get_current_time返回时间数学计算(12034)*2调用 calculate返回 308模拟天气上海适合散步吗调用 get_weather_city结合数据给出建议创建备忘记得提醒我明天交周报调用 create_memo然后确认超出能力帮我订一张飞往三亚的机票礼貌说明当前没有订票工具如果出现模型不输出 JSON而是直接给出文字回复可能表现在日志中extract_action返回None循环直接结束并把文字当作最终回答。这种情况通常可以通过改进提示词或者在调用接口时启用 JSON 输出模式解决。6. 常见问题与排查思路6.1 大模型调用失败现象请求/chat返回 500后台日志提示Connection error或AuthenticationError。排查步骤检查LLM_API_KEY是否正确配置。使用 curl 直接测试大模型接口连通性。确认LLM_BASE_URL路径是否正确例如是否包含/v1。确认所选模型名称是否存在且当前账号有权限访问。解决方案修正环境变量如果是网络策略问题请与模型服务商确认访问方式不要盲目重试。6.2 Agent 陷入工具调用死循环现象模型反复输出动作但始终不给最终回答直到达到MAX_AGENT_STEPS。常见原因工具返回结果格式与提示词描述不一致。模型依赖同一个工具的同一结果却无法正确推理。工具执行失败后返回的错误信息不够明确模型只能反复尝试。解决方案在每次工具返回后把“观察结果 是否成功”都拼入上下文也可以增加一个“若工具已经返回结果必须给出最终回答”的强约束提示词。更重要的是把MAX_AGENT_STEPS设为一个合理上限避免无限循环消耗 Token。6.3 角色人设逐渐消失现象多轮对话后C1 的说话方式越来越像普通模型不再保持人设。原因历史消息中保留了大量普通风格的回复系统提示词没有被重新强调。解决方案每轮调用都保留 System Prompt并且定期对历史消息做摘要压缩。如果发现人格偏移可以在历史消息中插入一条“请继续保持你的仕女风格”的隐式提醒。6.4 上下文过长导致报错现象长会话后请求报错提示超出上下文长度。原因没有限制历史消息数量或 Token 数。解决方案改造run_agent在向大模型发送消息前计算回复的 Token 约数只保留最近若干条或者使用摘要模块把旧消息压缩成一段短摘要再接入上下文。6.5 并发场景下会话错乱现象多个用户同时访问互相看到对方的对话内容。原因示例代码直接使用内存字典保存sessions没有加锁也没有区分不同服务实例。解决方案将会话数据迁移到 Redis以user_id作为 key并设置过期时间。在多实例部署时选择 Redis 这类外部存储可以保证会话数据一致。问题现象常见原因解决思路启动失败提示缺少依赖没有安装 requirements 中依赖在虚拟环境安装依赖无回复大模型 API 不可用或密钥错误检查配置和网络工具调用返回空参数名不匹配检查工具参数名称与描述保持一致角色语气不自然System Prompt 太长或历史污染精简提示词维护历史消息多用户会话串号内存会话未隔离用 Redis 存储会话7. 最佳实践与工程建议从“能跑的 Demo”到“能上线的服务”之间还隔着很多工程细节。这里把 C1 项目中沉淀出的一些经验分享出来。7.1 人设与系统提示词管理不要把 System Prompt 写在一个孤立字符串里直接发出去。建议把“人设描述”“任务规则”“工具清单”拆分成独立模板组合后发送。这样便于测试不同的人格版本也方便在没有 C1 人设的情况下做模型回归测试。进一步可以引入版本化提示词管理每次修改都记录版本号线上出问题时可以快速回滚到上一个稳定版本。7.2 工具权限与安全边界AI 代理人能调用工具意味着它掌握了系统变更能力。生产环境必须遵循最小权限原则每个工具都要明确角色权限禁止代理人访问操作者没有授权的资源数据库写入、发送消息、执行命令等敏感动作必须加审批或二次确认机制。在 C1 的例子中create_memo只是打印日志并未真正写入数据库。上线时如果要接入真实数据库要记得做数据校验、参数白名单、事务处理和操作审计。另外要特别注意不要在提示词中描述与实际工具能力不一致的功能。比如没有真实天气 API就不应该让模型声称“查询了真实天气”否则会产生严重的信任问题。7.3 日志与可观测性Agent 循环天然是逐步执行的这为日志记录提供了很大便利。建议在每一步记录模型输入的 Token 数。模型输出的原始文本。提取出的工具动作。工具执行耗时和结果。最终回答内容。这些日志既能用于排障也能用于评估模型表现、统计成本。日志中如果包含用户输入要注意脱敏处理尤其是手机号、身份证号等敏感信息。7.4 成本与性能优化每次 Agent 循环都需要调用大模型多步任务可能会产生大量 Token。项目初期就要控制成本常见手段包括设置单次会话最大上下文长度。限制MAX_AGENT_STEPS。使用缓存策略对所有用户都相同的工具结果如天气做短时间缓存。给模型一个“完成任务立刻停止”的明确指令。如果响应速度优先可以用流式输出让用户先看到模型正在思考而不是一直等待完整结果。7.5 模型能力回退策略大模型不是永远可靠的。当循环超过限制或工具连续执行失败时建议给用户一个明确的兜底回复比如“暂时无法完成这个任务请稍后重试或联系人工”。如果未来接入多个大模型还需要在 Agent 循环外层封装一层模型路由逻辑用来判断主模型不可用时切换到备用模型。路由逻辑要独立于 Agent 核心避免把切换模型的代码混杂在业务逻辑里。8. 总结与学习路线本文以“骨壳工坊AI代理人 仕女型C1”为案例完整实现了一个基于 Python 和 FastAPI 的轻量级 AI 代理人服务。我们重点围绕四个问题展开如何用 System Prompt 控制角色人格、如何定义和注册工具、如何实现 ReAct 循环、如何把 Agent 服务化并排错。这套代码虽然简单但已经具备继续扩展的基础骨架。下一步你可以从四个方向深入接入长期记忆把用户偏好、历史重要结论存入向量数据库让 C1 拥有跨会话记忆。增加 RAG 知识库为 C1 接入品牌资料、场馆信息、常见问答文档增强回答准确性。引入语音与多模态能力为 C1 增加语音识别、语音合成、形象动画渲染能力让“仕女型”角色体验更立体。构建多 Agent 协作把“C1”拆成“接待助手”“日程管家”“讲解专家”等多个子 Agent由主代理负责意图路由。实际使用中你会发现角色人设、工具调用和工程稳定性是同等重要的三件事。人设决定了用户体验的独特感工具调用决定了任务的完成率工程稳定性则决定了这个系统能不能真正放到生产环境里。建议先跑通本文的 Demo再逐步替换成你所在业务的真实工具和真实数据源同时补上监控、安全、测试这些生产必备环节。如果文章中的示例对你的项目有启发不妨直接照着改一版自己的 AI 代理人。

相关推荐

AI代理人工程化落地:角色配置、工具调用与安全治理实践
AI代理人工程化落地:角色配置、工具调用与安全治理实践

如果你最近在关注 AI 应用,应该会注意到一个现象:AI 产品的命名正在从“助手”“机器人”这种工具感很强的词,慢慢转向“代理人”“数字员工”甚至“仕女型 C1”这种带有角色和型号特征的叫法。表面上这是市场包装,实际上它反映了… · 2026/9/26 8:27:51

高性能密码学库设计:从指令集加速到工程落地
高性能密码学库设计:从指令集加速到工程落地

做网络安全和基础架构这些年,我最怕听到的一句话就是“再压一压性能”。在高并发场景里,密码学库往往是最容易被忽略却又绕不过去的瓶颈点。一个高性能密码学库,不再只是“能加密就行”,而是要在保证安全的前提下,把每… · 2026/9/26 8:27:51

C# WinForm圆形进度条自绘实现:GDI+绘制原理与避坑指南
C# WinForm圆形进度条自绘实现:GDI+绘制原理与避坑指南

简介:C# WinForm开发中的圆形进度条往往需要通过自定义控件实现,这份示例源码提供了从窗体布局到控件绘制的完整参考。项目基于VS2019与.NET Framework 4.7.2构建,控件DLL按4.0版本编译,兼顾新老环境的兼容运行。压缩包共20个文件… · 2026/9/26 8:27:51

GoFly双端架构实战:SAAS多租户数据分离与隔离验证
GoFly双端架构实战:SAAS多租户数据分离与隔离验证

简介:GoFly快速开发后台管理系统框架是一套面向中后台系统开发者的前后端分离解决方案,基于Go语言与Vue.js技术栈构建,集成总管理系统admin端与业务管理系统business端,并支持SAAS多账号数据分离,适合需要快速搭建云服… · 2026/9/26 9:12:30

C语言指针与数据结构实战:从链表到队列的完整攻略
C语言指针与数据结构实战:从链表到队列的完整攻略

指针这东西,学C语言的人没几个不头疼的。但如果你准备啃链表、栈、队列这些动态数据结构,指针就不是“要不要学”的问题,而是“能不能绕开”的问题——绕不开,它们是同一件事的两面:指针提供了操作内存地址的能力&… · 2026/9/26 9:12:30

Windows防火墙入站出站规则详解:从原理到命令行实战
Windows防火墙入站出站规则详解:从原理到命令行实战

1. 被大多数人忽略的Windows防火墙真相很多人对Windows自带防火墙的态度就两个字:关掉。装完某个软件连不上网,第一反应是"把防火墙关了试试";配个本地开发环境端口不通,也是先关防火墙。这个操作确实能解决眼前问题&am… · 2026/9/26 9:12:30

数据结构课设实战:约瑟夫环、BST与排序算法C语言实现
数据结构课设实战:约瑟夫环、BST与排序算法C语言实现

简介:这份资源是湖南科技大学计算机科学与工程学院第二学期数据结构课程设计报告,面向正在修读数据结构课程、需要完成课设或复盘算法实验的本科生。报告以docx文档形式呈现,压缩包内共1个文件,约234KB,内容按项目名称… · 2026/9/26 9:12:24

Windows U盘拒绝访问的真正原因与分层修复方案
Windows U盘拒绝访问的真正原因与分层修复方案

1. 问题本质与真实场景还原:这不是U盘坏了,而是Windows在“锁门”你插上U盘,双击图标——弹窗:“拒绝访问”。右键“以管理员身份运行”?没用。换台电脑试试?好使。再插回原机,还是拒绝。这时候… · 2026/9/26 9:12:24

西安电子科技大学数据库期末试卷真题解析:SQL、范式与事务高频考点
西安电子科技大学数据库期末试卷真题解析:SQL、范式与事务高频考点

简介:这份资源是西安电子科技大学数据库课程的期末试卷真题PDF,含参考答案,面向正在备考数据库原理、需要刷题巩固的本科生与考研复习者。试卷覆盖数据库系统基础、关系模型与E-R设计、SQL的DDL/DML/TCL语句、范式与关系代数、事务ACID与并发… · 2026/9/26 9:12:24

数据库课后习题答案别硬背:当测试用例集刷,效率翻倍
数据库课后习题答案别硬背:当测试用例集刷,效率翻倍

简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、… · 2026/9/26 0:00:21

OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置
OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 0:00:40

向下兼容与向上兼容:接口设计中的兼容性策略与工程实践
向下兼容与向上兼容:接口设计中的兼容性策略与工程实践

一次版本升级事故,是很多团队绕不过去的坎。线上环境里,服务端明明已经上线了新版接口,老的移动端还在照着旧文档传参数。请求一到网关,校验直接拒绝,用户操作失败,客服群炸了锅,开发群里开始互… · 2026/9/26 0:00:46

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码