使用 SageMaker AI 与 Bedrock AgentCore 构建智能体工作流
本文介绍如何将 Amazon SageMaker AI 上兼容 OpenAI 的终端节点与 Amazon Bedrock AgentCore 运行时结合,构建多智能体工作流,每个专用智能体使用最适合其任务的模型。文章还展示了如何获取 SageMaker 终端节点的令牌级可观测性,而 Strands Agents 默认不提供此项功能。
在构建智能体工作流时,一个常见挑战是如何将托管的基座模型与您自己的成本优化或领域专用模型混合使用,而无需重写智能体框架。本文介绍了如何将 Amazon SageMaker AI 上的 OpenAI 兼容终端节点与 Amazon Bedrock AgentCore 运行时(Amazon Bedrock AgentCore 的一项功能)及其托管部署相结合。专用智能体可以协作处理复杂任务,同时各自使用最适合其工作的模型。这种组合可以在单个生产级架构中实现成本优化、数据驻留和模型灵活性。
解决方案概述:架构通过单个 Amazon Bedrock AgentCore 容器连接三条模型托管路径。协调器智能体(Bedrock 上的 Claude Haiku 4.5)负责对用户意图进行分类,并通过全局跨区域推理路由任务;预算智能体(Bedrock 上的 Claude Sonnet 4.6)使用结构化的 Pydantic 输出处理 50/30/20 预算分解;财务分析智能体(SageMaker AI 上的 Qwen 3.5 9B)使用工具调用来进行股票分析和投资组合构建。需要注意,Amazon Bedrock 模型可用性因 AWS 区域而异,请参阅文档。
用户请求进入 AgentCore 运行时中的协调器智能体。协调器使用 Strands Agents 的 agents as tools 模式将请求路由到预算智能体或财务分析智能体。预算智能体通过 Amazon Bedrock 调用 Claude Sonnet 4.6,财务分析智能体通过 SageMaker AI 实时终端节点使用 OpenAI 兼容 API 调用 Qwen 3.5 9B。结果通过协调器返回给用户。完整源代码见 GitHub 仓库。
前提条件:需要具有 SageMaker AI、Amazon Bedrock 和 AgentCore 权限的 AWS 账户;安装相关 Python 包;拥有包含 sagemaker:InvokeEndpoint 和 sagemaker:CallWithBearerToken 的 IAM 角色;启用 Claude Haiku 4.5 和 Claude Sonnet 4.6 的 Bedrock 模型访问;Python 3.12 以上。
步骤1:在 SageMaker AI 上部署 Qwen 3.5 9B。使用 vLLM 深度学习容器镜像 vllm:0.22.1-gpu-py312-cu130,在 ml.g6e.2xlarge 上部署。设置环境变量如 SM_VLLM_MODEL、SM_VLLM_TENSOR_PARALLEL_SIZE、SM_VLLM_MAX_MODEL_LEN,然后创建模型、端点配置和端点。
步骤2:构建多智能体系统。SageMaker AI 的 OpenAI 兼容 API 需要 bearer token,且 token 会过期,因此对于长时间运行的智能体会话,需要在每次请求时刷新 token。可以使用 httpx.Auth 子类实现自动刷新。然后使用 Strands Agents 的 agents as tools 模式,为每次调用创建新的智能体实例。
步骤3:部署到 Amazon Bedrock AgentCore 运行时。使用 bedrock-agentcore-starter-toolkit 进行配置和启动,设置环境变量如 SAGEMAKER_ENDPOINT_NAME、SAGEMAKER_REGION 和 AGENT_OBSERVABILITY_ENABLED。
可观测性配置:AgentCore 运行时使用 OpenTelemetry 自动对智能体进行插桩,但这种插桩并不均匀地扩展到每个模型提供商。Amazon Bedrock 模型调用会自动获得包含令牌数的完整生成式 AI span,但 SageMaker OpenAI 兼容端点(通过 Strands OpenAIModel)不会自动获得令牌遥测。根本原因是 Strands 的 OTEL 集成会发出工具调用和智能体生命周期事件的 span,但不会为 OpenAIModel 提供者发出包含令牌属性的 gen_ai.chat span。AgentCore 的自动插桩只能识别通过 boto3 进行的 Amazon Bedrock 模型推理调用。
解决方案是手动发出一个 gen_ai.chat span,包裹 SageMaker 智能体调用,并从 Strands 的内部 AgentResult.metrics.accumulated_usage 中提取令牌使用量。关键细节:Strands 内部使用 inputTokens、outputTokens 和 totalTokens 作为键,仅当模型提供程序返回使用数据时才会填充该字典。
为什么 stream_options 对 vLLM 是必须的?默认情况下,vLLM 在流式响应中不包含 usage chunk。Strands 接收文本块,但永远收不到最终的使用对象,因此 accumulated_usage 保持为零。添加 stream_options: {"include_usage": True} 可让 vLLM 发送带有令牌计数的额外最终块。没有此参数,gen_ai.chat span 将报告 0 个令牌。
逐步配置:启用 Amazon CloudWatch Transaction Search;安装 strands-agents[otel];设置 AGENT_OBSERVABILITY_ENABLED=true;使用 opentelemetry-instrument 作为容器 CMD;向 OpenAIModel params 添加 stream_options;创建自定义 gen_ai.chat span。示例 trace 输出显示了输入令牌、输出令牌、总令牌和持续时间。
关键学习:Bedrock AgentCore 自动插桩 Bedrock 调用;SageMaker OpenAI 端点需要手动 span;令牌使用需要 stream_options;使用 result.metrics.accumulated_usage;AWS X-Ray 采样率很重要(默认1%会丢弃大部分 trace,开发时建议使用100%);每次请求使用新的智能体实例以避免并发问题。
扩展模式:可以将 SM_VLLM_MODEL 指向 S3 上的微调检查点,以替换为微调模型,认证层、OTEL span 和 AgentCore 部署保持不变;也可以使用推理组件进行 A/B 测试。