使用Amazon Bedrock AgentCore Harness构建无服务器图像编辑代理
本文介绍如何构建一个无服务器图像编辑器,用户上传照片后用自然语言描述编辑需求,几秒内即可获得结果。代理运行在AgentCore harness上,无需自定义编排代码。通过单一部署命令即可部署完整解决方案,包括身份验证、加密存储、三个图像编辑工具和React前端。基础设施使用AWS CDK定义。
构建一个能够根据自然语言编辑图像的AI代理通常需要编排循环、工具路由、内存管理以及运行它的计算环境。Amazon Bedrock AgentCore harness通过配置处理了整个流程。您只需声明代理的职责,harness就会在一个有状态、隔离的微VM中运行它,内置内存、工具路由和可观测性。
本文介绍了如何构建一个无服务器图像编辑器,用户上传照片,用简单的英语描述编辑需求,然后在几秒内收到结果。代理运行在AgentCore harness上,无需自定义编排代码。通过单一部署命令,您可以部署完整的解决方案,包括身份验证、加密存储、三个图像编辑工具和React前端。基础设施使用AWS Cloud Development Kit(AWS CDK)定义。
图像编辑应用程序
该应用程序接受诸如“将汽车颜色改为蓝色”或“将图像向右扩展200像素”之类的提示。由Claude Sonnet 4.6驱动的代理将需求分解为一系列步骤,并编排工具调用,每个工具与不同的Stability AI模型关联。然后执行编辑,使用微VM上的shell命令应用水印(无token成本),并返回结果。
此应用程序展示了AgentCore harness的以下能力:
- 配置驱动的代理创建:代理完全通过API参数定义,无需Python编排代码、框架或容器。
- 每次调用模型切换:前端将基本聊天路由到Claude Haiku 4.5,将编辑路由到Claude Sonnet 4.6,代理在模型切换时保持对话上下文。
- 每次调用角色覆盖:用户选择行业角色(房地产、零售、汽车),这些角色会注入特定领域的系统提示,无需重新部署。
- AgentCore内存:将对话历史存储在AgentCore服务中30天。代理在会话中的各轮次之间保持完整上下文,因此可以引用先前的编辑,而无需前端重新发送历史。此示例将会话ID保存在localStorage中,因此对话在浏览器刷新后仍然存在。清除浏览器数据会在前端启动新会话,但对话历史仍可通过ListEvents API在AgentCore中获取。
- AgentCore Gateway与MCP:三个AWS Lambda支持的工具通过Model Context Protocol(MCP)暴露,并具有语义路由。代理根据提示选择正确的工具。
- InvokeAgentRuntimeCommand:每次编辑后,Python脚本直接运行在AgentCore运行时微VM上以添加水印。无需模型推理,不消耗token。
解决方案概述
图像编辑应用程序的架构有四层:
- 托管在AWS Amplify上的React前端,用户上传图像、绘制遮罩并输入编辑指令。
- AWS Lambda代理,作为浏览器凭据与harness API之间的安全边界,并控制允许哪些系统提示。
- Amazon Bedrock AgentCore harness代理,具有AgentCore Memory以实现对话持久性。
- 三个工具Lambda函数,通过Amazon Bedrock调用Stability AI基础模型进行图像生成。
使用配置创建代理
使用AgentCore harness,代理定义是传递给create_harness API的一组参数。以下是CDK部署期间创建代理的核心配置代码:
harness_params = {
'harnessName': 'img_editor',
'executionRoleArn': execution_role_arn,
'model': {'bedrockModelConfig': {'modelId': 'us.anthropic.claude-sonnet-4-6'}},
'systemPrompt': [{'text': system_prompt}],
'tools': [{'type': 'agentcore_gateway', 'name': 'gateway',
'config': {'agentCoreGateway': {'gatewayArn': gateway_arn}}}],
'allowedTools': [
'inpaint-target___inpaint',
'outpaint-target___outpaint',
'search-replace-target___search_and_replace',
],
'maxIterations': 10,
'timeoutSeconds': 300,
}
harness_params['memory'] = {
'agentCoreMemoryConfiguration': {'arn': memory_arn}
}
response = client.create_harness(**harness_params)这就是整个代理。没有编排循环,没有工具执行逻辑,没有流式处理器,没有错误重试代码。AgentCore harness处理了所有这些。
通过AgentCore Gateway声明工具
赋予代理访问工具的权限通常需要编写代码来接收来自模型的工具调用、解析参数、调用目标函数、处理错误并将结果返回。使用harness,您可以跳过所有这些。您在AgentCore Gateway上声明工具模式并将其指向Lambda函数。Harness发现工具,在推理过程中将它们呈现给模型,通过Gateway调用选定的工具,并自动将结果反馈回对话。
以下是如何在CDK堆栈中声明搜索替换工具:
this.gateway.addLambdaTarget('SearchReplaceTarget', {
gatewayTargetName: 'search-replace-target',
lambdaFunction: this.searchReplaceLambda,
toolSchema: agentcore.ToolSchema.fromInline([{
name: 'search_and_replace',
description: '通过描述在图像中查找对象并替换。不需要遮罩。当用户想要替换特定对象时使用。',
inputSchema: {
type: agentcore.SchemaDefinitionType.OBJECT,
properties: {
source_image_key: { type: agentcore.SchemaDefinitionType.STRING },
search_prompt: { type: agentcore.SchemaDefinitionType.STRING },
prompt: { type: agentcore.SchemaDefinitionType.STRING },
},
required: ['source_image_key', 'search_prompt', 'prompt'],
},
}]),
});代理读取这些工具描述并根据用户提示选择正确的工具,无需路由逻辑。Harness通过模型的推理处理工具选择。
每次调用的模型和角色切换
Harness在每次调用时接受一个模型参数。传递不同的模型ID会改变处理该轮对话的基础模型。Harness自动从AgentCore Memory加载完整对话历史,并为新模型格式化,因此上下文无需额外代码即可传递。您无需编写模型切换逻辑、历史检索或输入格式化。Harness基于单个参数变化在内部管理所有这些。
Lambda代理利用这一点将基本聊天路由到Haiku,将图像编辑路由到Sonnet。
invoke_params = {
'harnessArn': harness_arn,
'runtimeSessionId': session_id,
'messages': [{'role': 'user', 'content': [{'text': input_text}]}],
'actorId': actor_id,
}
if model_override:
invoke_params['model'] = {
'bedrockModelConfig': {'modelId': model_override}
}
if persona_text:
invoke_params['systemPrompt'] = [{'text': persona_text}]
response = client.invoke_harness(**invoke_params)前端根据提示是否包含编辑关键词来决定使用哪个模型。像“hi”或“你能做什么”这样的短消息会发送到Haiku以获得更低延迟,编辑则发送到Sonnet以获得更高质量的工具选择。用户也可以从菜单中手动选择模型。
AgentCore Memory保留完整的对话历史,无论harness中配置的模型如何更改。当Haiku收到“蓝色的怎么样?”而之前Sonnet处理了“把车变成黑色”时,Haiku知道“蓝色”指的是汽车,因为Memory将完整历史提供给任何活跃的模型。
后处理:使用shell命令(无token成本)
代理生成图像后,我们直接运行Python脚本在harness微VM上添加水印。这使用InvokeAgentRuntimeCommand,它提供对代理环境的shell访问,无需通过模型。
script = '\n'.join([
'from PIL import Image, ImageDraw, ImageFont',
'import boto3, io',
's3 = boto3.client("s3")',
f'obj = s3.get_object(Bucket="{bucket_name}", Key="{result_key}")',
'img = Image.open(io.BytesIO(obj["Body"].read())).convert("RGBA")',
'# ... 平铺水印文本 ...',
's3.put_object(Bucket=bucket, Key=key, Body=buf.getvalue())',
])
encoded_script = base64.b64encode(script.encode()).decode()
client.invoke_agent_runtime_command(
agentRuntimeArn=harness_arn,
runtimeSessionId=session_id,
body={'command': f'echo {encoded_script} | base64 -d | python3'},
)这种模式对于确定性后处理非常有用:在发送给模型之前调整图像大小(节省输入token)、验证代理输出、提取结构化数据或应用业务逻辑。微VM默认有Python和bash,您还可以在运行时安装额外的包。
由于harness仅通过配置驱动,没有代理脚本可以添加自定义逻辑。InvokeAgentRuntimeCommand是在代理运行的同一微VM上运行您自己的代码但位于代理循环之外的方式。Lambda代理在代理完成其轮次后调用它。命令执行、工作完成并返回。代理不知道发生了什么事。
前提条件
要部署此解决方案,您需要:
- 具有创建IAM角色、Lambda函数、S3存储桶、Cognito池和AgentCore资源权限的AWS账户。
- Node.js 20.x或更高版本。
- Python 3.13或更高版本(用于Lambda函数运行时)。
- AWS CLI 2.x配置了凭证。
- 在Amazon Bedrock中访问Anthropic Claude模型(Sonnet、Haiku)。
- 在Amazon Bedrock中访问Stability AI模型。
- 预计部署时间3到5分钟。
部署解决方案
部署脚本端到端处理所有事情:安装先决条件、打包Lambda依赖、部署CDK堆栈、构建前端、上传到Amplify并创建测试用户。
克隆GitHub仓库并导航到项目目录:
git clone https://github.com/aws-samples/sample-serverless-image-editing-agent-bedrock-agentcore-harness
cd sample-serverless-image-editing-agent-bedrock-agentcore-harness运行部署脚本:
./deploy.sh最后,它会打印出实时URL和登录凭证。
CDK堆栈在单个AWS CloudFormation堆栈中创建所有资源。解决方案使用Amazon Cognito(用户池和身份池)处理身份验证。图像存储在由AWS KMS加密的S3存储桶中。图像编辑能力由三个Lambda函数提供,这些函数通过AgentCore Gateway暴露为MCP工具。这些工具由配备内存的AgentCore harness代理编排,通过Lambda代理访问。前端方面,AWS Amplify应用程序提供基于React的用户界面。
操作指南
登录后,编辑器左侧显示画布,右侧显示聊天界面。
- 上传图像:图像上传到S3中用户身份范围内的前缀。
- 描述编辑:在聊天输入中输入自然语言指令。对于对象替换(例如“将天空改为日落”),代理会自动使用搜索替换。
- 绘制遮罩进行区域编辑:要编辑图像中的特定区域,在画布上绘制遮罩定义区域,然后输入要在遮罩区域生成的内容。
- 查看结果:编辑后的图像出现在聊天线程中,带有由微VM shell命令应用的平铺水印。“幕后”面板显示使用了哪个模型、调用了哪个工具、token计数、延迟以及是否应用了水印。
- 可选地切换模型:用户可以从菜单中选择模型以覆盖默认路由。
此解决方案展示了AgentCore harness如何简化AI代理的构建和部署,使其成为无服务器图像编辑等应用的强大工具。