re:Invent参会指南太复杂?手把手教你开发专属Agent,解锁MCP与沙盒执行黑科技!

发布时间:2026/10/18 23:16:12
re:Invent参会指南太复杂?手把手教你开发专属Agent,解锁MCP与沙盒执行黑科技!
1. 从 re:Invent 参会痛点说起为什么需要一个专属 Agent每年 re:Invent 的议程表一放出来我第一反应不是兴奋而是头大。几千场 session、好几层展区、几十个技术方向光是把「我想听的」和「我能赶上的」对齐就够做一张 Excel 表了。更别说现场临时改议程、某个 session 爆满要换场、想找某个 booth 的具体位置——这些信息散落在官网、App、邮件和现场大屏里靠人脑记根本扛不住。这就是我决定自己搭一个参会 Agent 的直接原因。它要能帮我做三件事查议程、算路线、总结内容。听起来简单但真动手就会发现一个「能跑」的 Agent 和一个「敢用」的 Agent 之间隔着三道坎。第一道坎是代码执行的安全边界。Agent 要处理时间表数据、算冲突、生成可视化最自然的做法是让它写 Python 跑一遍。可如果这段代码直接在你本地环境执行一个死循环就能把机器拖死更别提万一模型抽风生成了删文件的语句。你需要一个沙盒代码在里面跑跑完即焚跟你的真实环境完全隔离。第二道坎是工具调用的标准化。查议程要调一个接口查地图要调另一个查餐饮又是一个。每接一个新工具就重写一套胶水逻辑Agent 代码会迅速变成一坨意大利面。MCPModel Context Protocol就是来解决这个问题的——它把工具调用抽象成统一协议Agent 像插 USB 一样接工具换工具不用改核心逻辑。第三道坎是模型调用的通道管理。你可能会试好几个模型每个模型一套 Key、一套 Base URL、一套参数格式切换起来极其烦人。尤其是做 Agent 的时候主模型、总结模型、代码模型可能不是同一个管理成本翻倍。这篇文章就按这三道坎来拆。我会带你从零搭一个能调用 MCP 工具、具备沙盒执行能力的参会 Agent模型调用统一走 TaoToken 的 Key/API 通道省掉多模型切换的麻烦。全程可复制会前跑通一个 Demo 完全够用。适合谁看正在做 Agent 但卡在工具集成或安全执行的开发者要去 re:Invent 想搞个实用小工具的参会者以及想理解 MCP 和沙盒执行到底怎么落地的人。不需要你有云账号本地 Python 环境加一个 API Key 就能开跑。2. TaoToken 前置准备统一 Key 与 API 通道配置在动手写 Agent 之前先把模型调用这条链路理顺。我试过同时管三四个模型的 Key每次切换都要改环境变量、改 Base URL、改请求格式调试的时候经常忘了自己现在用的是哪个。后来统一走 TaoToken 的 API 通道一个 Key 覆盖多个模型Base URL 固定切换模型只改一个 model 字段省心很多。TaoToken 在这里的角色是「统一入口」你的 Agent 代码只认一个 API 地址和一个 Key背后调哪个模型由请求里的 model 参数决定。这样你的 MCP 工具层、沙盒执行层都不用关心模型是谁只管发请求收结果。2.1 获取 API Key打开 TaoToken 控制台进入 API Keys 页面创建一个新 Key。建议给这个参会 Agent 单独建一个 Key方便后面按项目排查用量。创建后立刻复制保存页面刷新后就看不到了。控制台地址https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentAPI Keys 直达https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content2.2 确认 Base URL 与模型 IDTaoToken 的 API 入口是https://taotoken.net/api注意这个地址不带任何查询参数直接作为 Base URL 用。模型 ID 你可以在模型对话页面先试一下确认哪个模型响应快、适合你的场景。模型对话入口https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content我实测下来参会 Agent 这种场景用中等规模的模型就够主推理用一个代码生成用一个总结用一个三个模型 ID 记下来后面写进配置。2.3 环境变量配置不要把手写的 Key 硬编码进代码。用环境变量本地开发用.env文件部署时用系统环境变量。先装依赖pip install openai python-dotenv requests然后在项目根目录建一个.env文件TAOTOKEN_API_KEYsk-你的Key粘贴在这里 TAOTOKEN_BASE_URLhttps://taotoken.net/api MODEL_MAIN你的主模型ID MODEL_CODE你的代码模型ID MODEL_SUMMARY你的总结模型ID注意.env要加进.gitignore别提交到仓库。如果你用 Cline 或 Claude Code 这类工具它们的配置文件里也是填这三件套Base URL 填https://taotoken.net/apiAPI Key 填你创建的 KeyModel ID 填你要用的模型。三件套缺一不可少一个就会报 401 或 model not found。2.4 验证通道连通在写 Agent 之前先用一段最小代码确认通道是通的import os from dotenv import load_dotenv from openai import OpenAI load_dotenv() client OpenAI( api_keyos.getenv(TAOTOKEN_API_KEY), base_urlos.getenv(TAOTOKEN_BASE_URL), ) resp client.chat.completions.create( modelos.getenv(MODEL_MAIN), messages[{role: user, content: 回复两个字通了}], ) print(resp.choices[0].message.content)跑出来打印「通了」说明 Key、Base URL、Model ID 三件套都对。如果报 401检查 Key 有没有复制完整如果报 model not found检查模型 ID 拼写如果报连接超时检查 Base URL 是不是写成了带路径的地址。这一步过了再往下走能省掉后面一半的排障时间。3. 可复制配置MCP 服务端与沙盒执行环境搭建这一节是核心。我会给你两份可直接复制的配置一份是 MCP 服务端的 JSON 配置一份是沙盒执行环境的搭建脚本。两份都跑通你的 Agent 就同时具备了「标准化调工具」和「安全跑代码」两个能力。3.1 MCP 服务端配置MCP 的架构是客户端-服务端模式。你的 Agent 是客户端工具以 MCP 服务端的形式注册进来。每个服务端声明自己提供哪些工具、每个工具接受什么参数。客户端启动时读取配置自动发现所有可用工具。新建一个mcp_config.json{ mcpServers: { schedule: { command: python, args: [-m, mcp_servers.schedule_server], env: { SCHEDULE_DATA_PATH: ./data/sessions.json } }, map: { command: python, args: [-m, mcp_servers.map_server], env: { MAP_API_KEY: ${MAP_API_KEY} } }, search: { command: python, args: [-m, mcp_servers.search_server], env: { SEARCH_API_KEY: ${SEARCH_API_KEY} } } } }这份配置声明了三个 MCP 服务端schedule管议程查询map管展区导航search管外部信息检索。每个服务端用commandargs启动env传环境变量。注意${MAP_API_KEY}这种写法是引用系统环境变量不要把真实 Key 写进 JSON。如果你用 Cline 或 Claude Code它们的 MCP 配置格式跟这个基本一致把这段 JSON 贴进对应的配置文件即可。Cline 的 MCP 设置在扩展面板里Claude Code 的在~/.claude/下的配置文件里。三件套Base URL、Key、Model ID在 MCP 配置里不出现那是模型调用层的事MCP 只管工具。3.2 沙盒执行环境沙盒的目标是Agent 生成的代码在一个隔离进程里跑有超时限制有资源上限跑完进程销毁不碰宿主环境。我用的是子进程 资源限制的方案不依赖 Docker本地就能跑。新建sandbox.pyimport subprocess import tempfile import os import resource import sys def run_in_sandbox(code: str, timeout: int 10, mem_mb: int 256) - dict: with tempfile.NamedTemporaryFile( modew, suffix.py, deleteFalse, dir/tmp ) as f: f.write(code) tmp_path f.name def limit(): resource.setrlimit( resource.RLIMIT_AS, (mem_mb * 1024 * 1024, mem_mb * 1024 * 1024) ) resource.setrlimit(resource.RLIMIT_CPU, (timeout, timeout)) try: proc subprocess.run( [sys.executable, tmp_path], capture_outputTrue, textTrue, timeouttimeout, preexec_fnlimit, cwd/tmp, ) return { ok: proc.returncode 0, stdout: proc.stdout[-4000:], stderr: proc.stderr[-2000:], } except subprocess.TimeoutExpired: return {ok: False, stdout: , stderr: 执行超时已终止} finally: os.unlink(tmp_path)这段代码做了四件事把 Agent 生成的代码写到临时文件用preexec_fn设置内存和 CPU 上限用subprocess.run带超时执行无论成功失败都删掉临时文件。cwd/tmp确保代码的工作目录是临时目录碰不到你的项目文件。实测下来256MB 内存加 10 秒超时处理议程数据、算路线、生成简单图表都够用。如果你的任务更重调大这两个参数但别去掉限制——没有限制的沙盒等于没有沙盒。3.3 把两者接起来Agent 的主循环逻辑是这样的用户提问 → 模型决定调哪个 MCP 工具或写代码 → 如果是工具调用走 MCP 客户端如果是代码执行走沙盒 → 结果回传给模型 → 模型生成最终回答。MCP 客户端的实现各家 SDK 略有不同核心是读取mcp_config.json启动服务端进程通过标准输入输出交换 JSON-RPC 消息。你不需要自己实现协议细节用官方 SDK 或框架自带的 MCP 支持即可。关键是配置文件里的路径和命令要对服务端能正常启动。沙盒这边把run_in_sandbox注册成一个工具函数模型生成代码后调用它把stdout和stderr回传。模型看到执行结果后继续推理直到给出最终答案。4. 验证请求跑通一个完整的参会 Agent 调用配置写完了现在跑一个真实场景验证。我用的测试问题是「帮我找出第一天上午 10 点到 12 点之间所有跟 Agent 相关的 session按展区位置排个序如果时间冲突就标出来。」4.1 完整调用代码import os import json from dotenv import load_dotenv from openai import OpenAI from sandbox import run_in_sandbox load_dotenv() client OpenAI( api_keyos.getenv(TAOTOKEN_API_KEY), base_urlos.getenv(TAOTOKEN_BASE_URL), ) TOOLS [ { type: function, function: { name: query_schedule, description: 按时间范围和关键词查询议程, parameters: { type: object, properties: { day: {type: string}, start: {type: string}, end: {type: string}, keyword: {type: string}, }, required: [day, start, end, keyword], }, }, }, { type: function, function: { name: run_code, description: 在沙盒中执行 Python 代码并返回结果, parameters: { type: object, properties: { code: {type: string, description: 要执行的 Python 代码} }, required: [code], }, }, }, ] def query_schedule(day, start, end, keyword): with open(./data/sessions.json, r, encodingutf-8) as f: sessions json.load(f) hits [ s for s in sessions if s[day] day and start s[start] end and keyword.lower() in s[title].lower() ] return json.dumps(hits, ensure_asciiFalse) def dispatch(name, args): if name query_schedule: return query_schedule(**args) if name run_code: result run_in_sandbox(args[code]) return json.dumps(result, ensure_asciiFalse) return 未知工具 messages [ {role: system, content: 你是 re:Invent 参会助理帮用户查议程、排路线、标冲突。}, {role: user, content: 找出第一天上午10点到12点所有 Agent 相关 session按展区排序标出时间冲突。}, ] for _ in range(6): resp client.chat.completions.create( modelos.getenv(MODEL_MAIN), messagesmessages, toolsTOOLS, ) msg resp.choices[0].message messages.append(msg) if not msg.tool_calls: print(msg.content) break 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: result, })4.2 预期结果模型第一轮会调query_schedule拿到 session 列表第二轮可能调run_code写一段排序和冲突检测的代码沙盒执行后返回结果第三轮模型整合成自然语言回答。你会在控制台看到类似这样的输出第一天上午 10:00-12:00 共找到 4 场 Agent 相关 session 1. 10:00-11:00 A 展区 Building Production Agents 2. 10:30-11:30 B 展区 MCP Deep Dive 3. 11:00-12:00 A 展区 Agent Observability 4. 11:30-12:30 C 展区 Sandbox Execution Patterns 冲突提示第 1 场和第 2 场时间重叠 30 分钟第 2 场和第 3 场重叠 30 分钟。 建议优先第 1 场和第 3 场都在 A 展区转场成本低。4.3 验证要点跑通这个流程说明四件事都对了TaoToken 通道正常模型有响应MCP 工具注册正常query_schedule被调用沙盒执行正常run_code返回了结果多轮工具调用循环正常模型连续调了多个工具。如果模型没有调工具而是直接编答案检查tools参数有没有传对以及 system prompt 里有没有明确要求它用工具。如果沙盒返回空结果检查run_in_sandbox的cwd和临时文件路径权限。5. 本篇常见错排查401、local proxy failed、reading choices、OAuth这一节按真实报错来。我把搭这个 Agent 过程中踩到的坑列出来你对照自己的报错找。5.1 401 Unauthorized最常见。原因就三个Key 没填、Key 填错、Key 过期。检查.env里的TAOTOKEN_API_KEY是不是完整复制了有没有多余空格。如果你用 Cline 或 Claude Code检查配置文件里的 Key 字段。三件套里 Key 错了就是 401Base URL 错了通常是连接失败或 404Model ID 错了是 model not found三者报错不一样别混。5.2 local proxy failed这个报错通常出现在你本地起了代理但代理没通或者环境变量里残留了HTTP_PROXY/HTTPS_PROXY指向一个不存在的端口。检查你的 shell 环境env | grep -i proxy如果有输出且指向你不认识的地址清掉unset HTTP_PROXY HTTPS_PROXY http_proxy https_proxy然后重跑验证脚本。TaoToken 的 API 地址直接访问即可不需要额外代理配置。5.3 reading choices 相关报错典型的是KeyError: choices或reading choices of undefined。这说明你拿到的响应体里没有choices字段通常是请求根本没成功返回的是一个错误对象。打印完整响应看看resp client.chat.completions.create(...) print(resp.model_dump())如果看到error字段按错误信息排查。常见的是模型 ID 不对或请求格式不对。还有一种情况是你用了某个 SDK 的旧版本响应结构和代码里的取值方式不匹配升级 SDK 即可。5.4 OAuth 相关报错如果你用 Claude Code 或类似工具可能会遇到 OAuth 相关的报错。这类工具默认走 OAuth 登录流程但你要用 API Key 通道的话需要在配置里显式指定 API Key 模式把 Base URL 和 Key 填进去。具体做法是在工具的配置文件里找到认证相关字段切换成 API Key 方式。三件套填全Base URL 填https://taotoken.net/apiKey 填你的 KeyModel ID 填你要用的模型。填完重启工具。5.5 MCP 服务端启动失败报错通常是command not found或ModuleNotFoundError。检查mcp_config.json里的command是不是你环境里的 Python 路径args里的模块名是不是存在。如果你用虚拟环境command要指向虚拟环境里的 Python不是系统 Python。可以在配置里写绝对路径command: /Users/you/project/.venv/bin/python5.6 沙盒执行超时如果run_in_sandbox频繁返回超时先看 Agent 生成的代码是不是有死循环。沙盒的超时限制就是防这个的超时被终止是正常行为。如果代码本身没问题但确实需要更长时间调大timeout参数。但别直接去掉限制去掉限制的沙盒在 Agent 场景下很危险。6. 会前跑通之后把 Agent 用起来Demo 跑通只是起点。真正去 re:Invent 之前你可以把这个 Agent 再往前推一步把议程数据换成最新的官方数据把地图服务接上真实的展区坐标把搜索工具指向你常用的技术资讯源。这样到了现场你掏出手机问一句「我现在在 B 展区接下来一小时有什么值得听的」它就能直接给你答案。如果你打算长期做 Agent 开发建议把模型调用统一走 Coding Plan省掉每次切模型改配置的麻烦。Coding Plan 入口https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content接入文档在这里MCP 配置和 API 调用的细节都能查到https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content最后说一个我踩过的坑沙盒的临时文件目录别设在项目目录下设到/tmp或系统临时目录。我有一次把dir设成了./tmp结果 Agent 生成的代码把项目里的文件列表读出来了虽然没造成破坏但暴露了隔离不彻底的问题。沙盒的工作目录和临时文件目录都要跟项目目录完全分开这是底线。