Amazon Bedrock AgentCore ハーネスを用いたサーバーレス画像編集エージェントの構築方法
AWS は Amazon Bedrock AgentCore ハーネスを用いたサーバーレス画像編集エージェントの構築ガイドを公開し、カスタムオーケストレーションコード不要で複雑な AI エージェントを迅速に実装可能であることを示した。
キーポイント
AgentCore ハーネスによる構成駆動型開発
Python のオーケストレーションコードやコンテナの構築を不要とし、API パラメータのみで状態管理、ツールルーティング、メモリ機能を備えたエージェントを作成できる。
動的なモデル切り替えとコンテキスト維持
チャットには Claude Haiku 4.5 を、複雑な編集タスクには Claude Sonnet 4.6 を使い分けつつ、セッション全体で会話履歴を保持する機能を実装している。
ドメイン特化型ペルソナの実装
不動産や小売など業界ごとのシステムプロンプトを動的に注入する「ペルソナオーバーライド」機能を、再デプロイなしで実現可能である。
マイクロ VM 環境での完全サーバーレス実行
AWS CDK を用いた単一コマンドのデプロイで、認証、暗号化ストレージ、画像編集ツール、およびウォーターマーク付与を含む完全なアプリケーションを構築する。
会話の永続化設定
harness_params に 'memory' キーを追加し、Amazon Bedrock AgentCore のメモリ ARN を指定することで、エージェント間の会話履歴を保持できます。
AgentCore Memory Configuration の使用
'agentCoreMemoryConfiguration' 構造体を用いて、外部のメモリリソース(ARN)をエージェントにバインドし、状態管理を実現します。
ツール宣言の簡素化
AgentCore Gateway を介して Lambda 関数とツールスキーマを宣言するだけで、モデルからの呼び出し解析やエラー処理などのオーケストレーションコードが不要になります。
重要な引用
The agent is defined entirely through API parameters. No Python orchestration code, no framework, no container.
AgentCore memory stores conversation history in the AgentCore service for 30 days.
Users select industry personas (Real Estate, Retail, Automotive) that inject domain-specific system prompts without redeploying.
harness_params['memory'] = {'agentCoreMemoryConfiguration': {'arn': memory_arn}}
That is the entire agent. No orchestration loop, no tool execution logic, no streaming handler, no error retry code.
The harness handles all of it.
影響分析・編集コメントを表示
影響分析
この発表は、AI エージェント開発における「コード不要(No-Code/Low-Code)」の潮流を加速させるものであり、従来の複雑なオーケストレーションロジックやインフラ管理の負担を大幅に軽減する。特に、構成駆動型で動的なモデル切り替えが可能になる点は、実運用環境でのコスト最適化と柔軟性を両立させる重要な技術的転換点となる。
編集コメント
AWS は「AgentCore」という新概念を打ち出し、AI エージェント開発のハードルを劇的に下げる方向性を明確に示しました。特に構成だけで複雑なロジックを実行できる点は、実務での導入スピードを劇的に変える可能性があります。
自然言語に基づいて画像を編集する AI エージェントを構築するには、オーケストレーションループ、ツールルーティング、メモリ管理、およびそれらを実行するための計算環境が必要です。Amazon Bedrock AgentCore harness は、設定によりこのスタック全体を処理します。エージェントの動作を宣言するだけで、ハルネスは状態を保持し、隔離されたマイクロ VM で実行します。これには組み込みのメモリ管理、ツールルーティング、および観測機能(observability)が含まれています。
本稿では、ユーザーが写真をアップロードし、平易な英語で編集内容を記述すると数秒で結果を受け取れるサーバーレス画像エディタの構築手順を解説します。このエージェントは、カスタムのオーケストレーションコードなしで AgentCore ハルネス上で動作します。認証、暗号化されたストレージ、3 つの画像編集ツール、および React フロントエンドを含む完全なソリューションを、単一のデプロイコマンドで展開します。インフラストラクチャは AWS Cloud Development Kit (AWS CDK) を用いて定義されています。
イメージ編集アプリケーション
このアプリケーションは、「車の色を青に変える」や「画像を右に 200 ピクセル拡張する」といったプロンプトを受け付けます。Claude Sonnet 4.6 に基づくエージェントが要件を一連のステップに分解し、それぞれが異なる Stability AI モデルに関連付けられたツールの呼び出しをオーケストレーションします。その後、編集を実行し、マイクロ VM 上のシェルコマンドを使用して透かし(ウォーターマーク)を適用し(トークンコストは発生しません)、結果を返します。
このアプリケーションは、以下の AgentCore ハーネスの機能を示しています:
- コンフィギュレーション駆動型のエージェント作成。エージェントは API パラメータのみで完全に定義されます。Python のオーケストレーションコードも、フレームワークも、コンテナも不要です。
- 各呼び出しごとのモデル切り替え。フロントエンドは基本的なチャットを Claude Haiku 4.5 にルーティングし、画像編集を Claude Sonnet 4.6 にルーティングします。エージェントはモデルの切り替えを超えて会話の文脈を保持します。
- 各呼び出しごとのペルソナ上書き。ユーザーは業界別ペルソナ(不動産、小売、自動車)を選択でき、これにより再デプロイすることなくドメイン固有のシステムプロンプトが注入されます。
- AgentCore メモリは、会話履歴を 30 日間 AgentCore サービス内に保存します。エージェントはセッション内のターンを超えて完全な文脈を保持するため、フロントエンドが履歴を再送信しなくても以前の編集内容を参照できます。このサンプルではセッション ID を localStorage に永続化しているため、ブラウザの更新後も会話が維持されます。ブラウザデータをクリアするとフロントエンド側で新しいセッションが始まりますが、会話履歴は ListEvents API を通じて AgentCore 内で引き続き利用可能です。
- MCP を備えた AgentCore Gateway。3 つの AWS Lambda ベースのツールが、セマンティックルーティングを伴う Model Context Protocol (MCP) を介して公開されています。エージェントはプロンプトに基づいて適切なツールを選択します。
- InvokeAgentRuntimeCommand。各編集の後、Python スクリプトが AgentCore ランタイムマイクロ VM 上で直接実行され、透かしの追加が行われます。モデルによる推論は不要で、トークンは消費されません。
ソリューション概要
画像編集アプリケーションのアーキテクチャには 4 つのレイヤーがあります。
- AWS Amplify でホストされる React フロントエンド。ユーザーはここで画像をアップロードし、マスクを描画して編集指示を入力します。
- ブラウザの認証情報とハーンズ API の間のセキュリティ境界として機能する AWS Lambda プロキシであり、許可されるシステムプロンプトを制御します。
- 会話の永続化のために AgentCore Memory を備えた Amazon Bedrock AgentCore ハーンズエージェントです。
- Amazon Bedrock を通じて Stability AI の基盤モデルを呼び出す画像生成用の 3 つのツール Lambda 関数です。

設定によるエージェントの作成
AgentCore ハーンズを使用すると、エージェント定義は create_harness API に渡されるパラメータのセットとなります。以下は、cdk deploy 時にエージェントを作成するプロビジョニングコードの中核部分です。
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}}}],
スコープをゲートウェイが公開する正確に 3 つのツールに限定し、ワイルドカードで全てのツールを許可しないようにします。
'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 ハンダリングが処理します。
AgentCore Gateway を通じたツールの宣言
エージェントにツールへのアクセス権限を与える通常の方法では、モデルからのツール呼び出しを受け取り、引数を解析し、対象関数を呼び出し、エラーを処理し、結果を返すためのコード記述が必要です。しかし、このハーンを使用すれば、そのような作業はすべて不要になります。ツールスキーマを AgentCore Gateway 上で宣言し、Lambda 関数を指し示すだけで済みます。ハーンが自動的にツールを発見し、推論時にモデルに提示します。選択されたツールは 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'],
},
}]),
});
エージェントはこれらのツール説明を読み、ユーザーの指示に基づいて適切なものを選択します。ルーティングロジックは不要です。ハーンスはモデルの推論を通じてツールの選択を処理します。
各呼び出しごとのモデルとペルソナの切り替え
ハーンスは、すべての呼び出しでモデルパラメータを受け付けます。異なるモデル ID を渡すことで、そのターンを担当するファウンデーションモデルを変更できます。ハーンスは自動的に AgentCore Memory から完全な会話履歴を読み込み、新しいモデル用にフォーマットするため、追加のコードなしで文脈が引き継がれます。モデル切り替えロジックや履歴取得、入力フォーマットの記述は不要です。ハーンスは単一のパラメータ変更に基づき、これらすべてを内部で管理します。
Lambda プロキシはこの機能を利用して、基本的なチャットを Haiku に、画像編集を Sonnet にルーティングします。
invoke_params = {
'harnessArn': harness_arn,
'runtimeSessionId': session_id,
'messages': [{'role': 'user', 'content': [{'text': input_text}]}],
'actorId': actor_id,
}
# 呼び出しごとにモデルを切り替え(チャットは Haiku、編集は Sonnet)
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」や「what can you do」のような短いメッセージは、低レイテンシを実現するために Haiku へ送信されます。一方、編集処理は高品質なツール選択を行う Sonnet へ送られます。また、ユーザーはメニューから手動でモデルを選択することも可能です。
AgentCore Memory は、ハッチス(harness)内で構成されたモデル変更に関わらず、会話履歴全体を保持します。Sonnet が「change the car to black」の処理を担当した後、Haiku が「how about blue?」を受け取った場合でも、Memory がアクティブなモデルに完全な履歴を提供するため、「blue」が車を指していることを理解できます。
シェルコマンドによる後処理(トークンコストなし)
エージェントが画像を生成した後、ハッチス上のマイクロVM上で直接 Python スクリプトを実行して透かしを追加します。これには InvokeAgentRuntimeCommand が使用され、モデルを経由せずにエージェントの環境にシェルアクセスを提供します。
シェルエスケープの問題を回避するために Python スクリプトを構築し、base64 でエンコードする
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()
マイクロVM上で実行:モデル推論なし、トークン消費なし
client.invoke_agent_runtime_command(
agentRuntimeArn=harness_arn,
runtimeSessionId=session_id,
body={'command': f'echo {encoded_script} | base64 -d | python3'},
)
このパターンは、決定論的な後処理に有用です。モデルへの送信前に画像をリサイズして入力トークンを節約したり、エージェントの出力に対して検証を実行したり、構造化データを抽出したり、ビジネスロジックを適用したりできます。マイクロVMにはデフォルトで Python と bash が用意されており、ランタイム時に追加のパッケージもインストール可能です。
ハッチは設定のみであるため、カスタムロジックを追加できるエージェントスクリプトは存在しません。InvokeAgentRuntimeCommand は、エージェントが実行されている同じマイクロVM上で、エージェントループの外側で独自のコードを実行するための手段です。Lambda プロキシは、エージェントのターンが終了した後にこれを呼び出します。コマンドが実行され、処理が行われ、結果が返されます。エージェントはその出来事自体を認識しません。
前提条件
このソリューションを展開するには、以下のものが必要です。
- AWS Identity and Access Management (IAM) ロール、Lambda 関数、Amazon Simple Storage Service (Amazon S3) バケット、Amazon Cognito プール、および AgentCore リソースを作成する権限を持つ AWS アカウントが必要です。
- Node.js 20.x 以降。
- Lambda 関数のランタイムには Python 3.13 以降が必要です。
- 認証情報を設定した AWS Command Line Interface (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 スack は、すべてのリソースを単一の AWS CloudFormation スタック内に作成します。本ソリューションでは、認証処理のために Amazon Cognito のユーザープールとアイデンティティプールの両方を利用しています。画像は、AWS Key Management Service (AWS KMS) 暗号化で保護された Amazon S3 バケットに保存されます。画像編集機能は、3 つの Lambda 関数によって提供され、これらは AgentCore Gateway を通じて MCP ツールとして公開されています。これらのツールは、メモリ機能を備えた AgentCore ハーネスエージェントによってオーケストレーションされており、Lambda プロキシを介してアクセス可能です。フロントエンドでは、React ベースのユーザーインターフェースを提供する AWS Amplify アプリケーションが稼働しています。
ウォークスルー
サインイン後、エディタは左側にキャンバス、右側にチャットインターフェースを表示します。
1. 画像をアップロードする。 画像は、ユーザーのアイデンティティにスコープされたプレフィックスの下で S3 にアップロードされます。
2. 編集内容を記述する。 チャット入力欄に自然言語による指示を入力してください。オブジェクトの置換(例:「空を夕焼けに変更」)の場合、エージェントは自動的に検索・置換機能を使用します。
3. リージョン固有の編集用のマスクを描画する。 画像の特定の領域を編集するには、キャンバス上にマスクを描画して対象領域を定義し、そのマスクされた領域に生成させる内容を記述してください。
4. 結果を確認する。 編集済みの画像はチャットスレッドに表示され、マイクロ VM シェルコマンドによって適用されたタイル状の透かしが付けられます。「Behind the Scenes」パネルでは、使用されたモデル、呼び出されたツール、トークン数、レイテンシ、および透かしの適用有無を確認できます。
5. オプションでモデルやペルソナを切り替える。 チャットの上部にあるメニューを使用して、推論モデルを変更したり、業界固有のペルソナに切り替えたりできます。この変更は会話履歴を保持したまま、次のメッセージから即座に有効になります。
このプロジェクトにおいてハッチス(harness)が具体的に削減したもの
本ソリューションでは、エージェントのオーケストレーションコードを記述する必要はありません。モデル呼び出しループも、ツール実行ハンドラーも、ストリーミングパーサーも、エラー再試行ロジックも、コンテナイメージも不要です。
私たちが実際に実装したのは以下の通りです。
- セキュリティバウンダリとして機能し、ハッチスに到達するシステムプロンプトを制御する Lambda プロキシ(80 行)
- 実際の画像処理を行う 3 つのツール用 Lambda 関数(Stability AI の各モデルごとに 1 つずつ)
- デプロイ時に create_harness API を呼び出すプロビジョニングスクリプト(AgentCore ハッチスはプレビュー段階であり、ネイティブの CDK コンストラクトはまだ提供されていません)
エージェント自体は設定によって構成されます。その動作を変更する(異なるモデルを使用、新しいツールの追加、指示の更新など)のは、コードデプロイではなく API 呼び出しです。
AgentCore Runtime を使用するべきタイミング
AgentCore ハーネスは、ツール呼び出しパターンが単純なエージェントに適しています。エージェントはプロンプトを受け取り、適切なツールを選択して呼び出し、その結果を返します。もし、ターン間の入力前処理や LangGraph 状態機械の実行、各モデル呼び出し前後での任意の Python コード実行など、カスタムオーケストレーションロジックが必要であれば、AgentCore Runtime を使用することで完全な制御権を得ることができます。
ハルネスと AgentCore Runtime の両方は、同じ基盤インフラストラクチャ(マイクロ VM、メモリ、ゲートウェイ、観測機能)上で動作します。複雑さが増すにつれて、まずはハーネスから始め、必要に応じて AgentCore Runtime へ移行することも可能です。
クリーンアップ
destroy スクリプトを実行すると、S3 バケットとアップロードされた画像を含むすべてのリソースが永久的に削除されます。続行する前に、保存したいデータは必ずバックアップしてください。
スタックの削除:
./destroy.sh
結論
AgentCore ハーネスを使用すれば、オーケストレーションコードを記述することなく、本番環境で利用可能な画像編集エージェントを構築できます。このエージェントは、設定と各呼び出し時のパラメータを通じて、ツールの選択、モデルの切り替え、ペルソナのカスタマイズ、会話の永続化、そして決定論的な後処理を自動的に処理します。各セッションは孤立したマイクロ VM 内で実行され、ここでシャールコマンドを実行して透かしの追加などのタスクを行ってもトークンコストは発生しません。
ツール呼び出しのパターンが単純なエージェントの場合、ハーンは運用上のオーバーヘッドを削減し、設定変更の速度で動作を反復できます。完全なソースコードと 1 コマンドでのデプロイスクリプトは GitHub で利用可能です。
AgentCore ハーンを使用するには、AgentCore ハーンドキュメント をご覧いただくか、価格や利用状況の詳細については Amazon Bedrock AgentCore の製品ページをご覧ください。
著者について
原文を表示
Building an AI agent that edits images based on natural language requires an orchestration loop, tool routing, memory management, and a compute environment to run it all. Amazon Bedrock AgentCore harness handles that entire stack with configuration. You declare what the agent does, and the harness runs it in a stateful, isolated microVM with built-in memory, tool routing, and observability.
This post walks through building a serverless image editor where users upload a photo, describe an edit in plain English, and receive the result in seconds. The agent runs on AgentCore harness without custom orchestration code. We deploy the full solution, including authentication, encrypted storage, three image editing tools, and a React frontend, with a single deployment command. The infrastructure is defined using AWS Cloud Development Kit (AWS CDK).
Image editing application
The application accepts prompts like “change the car color to blue” or “extend the image 200 pixels to the right.” An agent powered by Claude Sonnet 4.6 breaks the requirement into a series of steps and orchestrates the tool calling, each associated with a different Stability AI model. Then it executes the edit, applies a watermark using a shell command on the microVM (no token cost), and returns the result.
This application demonstrates the following AgentCore harness capabilities:
- Configuration-driven agent creation. The agent is defined entirely through API parameters. No Python orchestration code, no framework, no container.
- Per-invocation model switching. The frontend routes basic chat to Claude Haiku 4.5 and edits to Claude Sonnet 4.6. The agent preserves conversation context across model switches.
- Per-invocation persona override. Users select industry personas (Real Estate, Retail, Automotive) that inject domain-specific system prompts without redeploying.
- AgentCore memory stores conversation history in the AgentCore service for 30 days. The agent retains full context across turns within a session, so it can reference prior edits without the frontend re-sending history. This sample persists the session ID in localStorage, so conversations survive browser refresh. Clearing browser data starts a new session on the frontend, but the conversation history remains available in AgentCore through the ListEvents API.
- AgentCore Gateway with MCP. Three AWS Lambda-backed tools are exposed through Model Context Protocol (MCP) with semantic routing. The agent selects the right tool based on the prompt.
- InvokeAgentRuntimeCommand. After each edit, a Python script runs directly on the AgentCore runtime microVM to add a watermark. No model reasoning, no tokens consumed.
Solution overview
The architecture of the image editing application has four layers.
- A React frontend hosted on AWS Amplify where users upload images, draw masks, and enter editing instructions.
- An AWS Lambda proxy that acts as a security boundary between browser credentials and the harness API, and controls which system prompts are allowed.
- An Amazon Bedrock AgentCore harness agent with AgentCore Memory for conversation persistence.
- Three tool Lambda functions calling Stability AI foundation models through Amazon Bedrock for image generation.

Creating the agent using configuration
With an AgentCore harness, the agent definition is a set of parameters passed to the create_harness API. Here is the core of our provisioning code that creates the agent during cdk deploy.
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}}}],
# Scope the agent to exactly the three tools the gateway exposes
# rather than allowing every tool with a wildcard.
'allowedTools': [
'inpaint-target___inpaint',
'outpaint-target___outpaint',
'search-replace-target___search_and_replace',
],
'maxIterations': 10,
'timeoutSeconds': 300,
}
# Attach memory for conversation persistence
harness_params['memory'] = {
'agentCoreMemoryConfiguration': {'arn': memory_arn}
}
response = client.create_harness(**harness_params)That is the entire agent. No orchestration loop, no tool execution logic, no streaming handler, no error retry code. The AgentCore harness handles all of it.
Declaring tools through AgentCore Gateway
Giving an agent access to tools normally requires writing code that receives tool calls from the model, parses arguments, invokes the target function, handles errors, and passes results back. With the harness, you skip all of that. You declare the tool schema on an AgentCore Gateway and point it at a Lambda function. The harness discovers the tools, presents them to the model during reasoning, invokes the selected tool through the Gateway, and feeds the result back into the conversation automatically.
Here is how we declared the search-and-replace tool in the CDK stack.
this.gateway.addLambdaTarget('SearchReplaceTarget', {
gatewayTargetName: 'search-replace-target',
lambdaFunction: this.searchReplaceLambda,
toolSchema: agentcore.ToolSchema.fromInline([{
name: 'search_and_replace',
description: 'Find an object in the image by description and replace it. '
+ 'Does NOT require a mask. Use when the user wants to replace a specific object.',
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'],
},
}]),
});The agent reads these tool descriptions and selects the right one based on the user prompt. No routing logic is required. The harness handles tool selection through the model’s reasoning.
Per-invocation model and persona switching
The harness accepts a model parameter on every invocation. Passing a different model ID changes which foundation model handles that turn. The harness automatically loads the full conversation history from AgentCore Memory and formats it for the new model, so context carries over without additional code. You do not need to write model-switching logic, history retrieval, or input formatting. The harness manages all of that internally based on a single parameter change.
The Lambda proxy uses this to route basic chat to Haiku and image edits to Sonnet.
invoke_params = {
'harnessArn': harness_arn,
'runtimeSessionId': session_id,
'messages': [{'role': 'user', 'content': [{'text': input_text}]}],
'actorId': actor_id,
}
# Switch model per invocation (Haiku for chat, Sonnet for edits)
if model_override:
invoke_params['model'] = {
'bedrockModelConfig': {'modelId': model_override}
}
# Switch persona per invocation (Real Estate, Retail, Automotive)
if persona_text:
invoke_params['systemPrompt'] = [{'text': persona_text}]
response = client.invoke_harness(**invoke_params)The frontend determines which model to use based on whether the prompt contains editing keywords. Short messages like “hi” or “what can you do” go to Haiku for lower latency. Edits go to Sonnet for higher quality tool selection. The user can also manually select a model from a menu.
AgentCore Memory preserves the full conversation history regardless of configured model changes in the harness. When Haiku receives “how about blue?” after Sonnet handled “change the car to black,” it knows “blue” refers to the car because Memory feeds the complete history to whatever model is active.
Post-processing with shell commands (no token cost)
After the agent generates an image, we run a Python script directly on the harness microVM to add a watermark. This uses InvokeAgentRuntimeCommand, which gives you shell access to the agent’s environment without going through the model.
# Build a Python script and base64 encode it to avoid shell escaping issues
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")',
'# ... tile watermark text across the image ...',
's3.put_object(Bucket=bucket, Key=key, Body=buf.getvalue())',
])
encoded_script = base64.b64encode(script.encode()).decode()
# Run on the microVM: no model reasoning, no tokens consumed
client.invoke_agent_runtime_command(
agentRuntimeArn=harness_arn,
runtimeSessionId=session_id,
body={'command': f'echo {encoded_script} | base64 -d | python3'},
)This pattern is useful for deterministic post-processing. Resize images before sending to a model (save input tokens), run validation on agent output, extract structured data, or apply business logic. The microVM has Python and bash available by default, and you can install additional packages at runtime.
Because the harness is configuration-only, there is no agent script where you can add custom logic. InvokeAgentRuntimeCommand is the way to run your own code on the same microVM where the agent runs, but outside the agent loop. The Lambda proxy calls it after the agent finishes its turn. The command executes, does the work, and returns. The agent does not know it had happened.
Prerequisites
To deploy this solution, you need the following.
- An AWS account with permissions to create AWS Identity and Access Management (IAM) roles, Lambda functions, Amazon Simple Storage Service (Amazon S3) buckets, Amazon Cognito pools, and AgentCore resources.
- Node.js 20.x or later.
- Python 3.13 or later (for Lambda function runtimes).
- AWS Command Line Interface (AWS CLI) 2.x configured with credentials.
- Access to Anthropic Claude models (Sonnet, Haiku) in Amazon Bedrock.
- Access to Stability AI models in Amazon Bedrock.
Estimated deployment time is 3 to 5 minutes.
Deploy the solution
The deploy script handles everything end-to-end. It installs prerequisites, bundles Lambda dependencies, deploys the CDK stack, builds the frontend, uploads it to Amplify, and creates a test user.
Clone the GitHub repository and navigate into the project directory.
git clone https://github.com/aws-samples/sample-serverless-image-editing-agent-bedrock-agentcore-harness
cd sample-serverless-image-editing-agent-bedrock-agentcore-harnessRun the deployment script.
./deploy.shAt the end, it prints the live URL and login credentials.
The CDK stack creates all resources in a single AWS CloudFormation stack. The solution uses Amazon Cognito with both a user pool and identity pool to handle authentication. Images are stored in an Amazon S3 bucket protected by AWS Key Management Service (AWS KMS) encryption. The image editing capabilities are powered by three Lambda functions, which are exposed as MCP tools through an AgentCore Gateway. These tools are orchestrated by an AgentCore harness agent equipped with memory, accessed via a Lambda proxy. On the frontend, an AWS Amplify application serves the React-based user interface.
Walkthrough
After signing in, the editor presents a canvas on the left and a chat interface on the right.
1. Upload an image. The image uploads to S3 under the user’s identity-scoped prefix.
2. Describe your edit. Enter a natural-language instruction in the chat input. For object replacement (“change the sky to a sunset”), the agent uses search-and-replace automatically.
3. Draw a mask for Region-specific edits. To edit a specific area of the image, draw a mask on the canvas to define the region, then enter what to generate in the masked area.
4. View the result. The edited image appears in the chat thread with a tiled watermark applied by the microVM shell command. The “Behind the Scenes” panel shows which model was used, which tool was called, token counts, latency, and whether the watermark was applied.
5. Optionally switch models or personas. Use the menus at the top of the chat to change the reasoning model or switch to an industry-specific persona. The change takes effect on the next message without losing conversation history.
What the harness specifically reduced for this project
The solution does not require lines of agent orchestration code. No model call loop, no tool execution handler, no streaming parser, no error retry logic, no container image.
What we did write.
- A Lambda proxy (80 lines) that acts as a security boundary and controls which system prompts reach the harness.
- Three tool Lambda functions (one per Stability AI model) that do the actual image processing.
- A provisioning script that calls the create_harness API during deployment (AgentCore harness is in preview and does not yet have a native CDK construct).
The agent itself is configuration. Changing its behavior (different model, new tool, updated instructions) is an API call, not a code deployment.
When to use AgentCore Runtime instead
AgentCore harness works well for agents with straightforward tool-calling patterns. The agent receives a prompt, picks a tool, calls it, and returns the result. If your agent needs custom orchestration logic, such as pre-processing inputs between turns, running a LangGraph state machine, or executing arbitrary Python before and after each model call, AgentCore Runtime gives you full control.
Both the harness and AgentCore Runtime run on the same underlying infrastructure (microVMs, Memory, Gateway, Observability). You can start with the harness and move to AgentCore Runtime as complexity grows.
Clean up
Running the destroy script permanently deletes all resources including the S3 bucket and uploaded images. Back up any data you want to keep before proceeding.
Delete the stack:
./destroy.shConclusion
AgentCore harness lets us build a production-ready image editing agent without writing orchestration code. The agent handles tool selection, model switching, persona customization, conversation persistence, and deterministic post-processing through configuration and per-invocation parameters. Each session runs in an isolated microVM where we can execute shell commands at no token cost for tasks like watermarking.
For agents with straightforward tool-calling patterns, the harness removes operational overhead and you can iterate behavior at the speed of a configuration change. The full source code and one-command deployment script are available on GitHub.
To get started with AgentCore harness, visit the AgentCore harness documentation or explore the Amazon Bedrock AgentCore product page for pricing and availability details.
About the authors
関連記事
OpenAI の初号ハードウェアは移動可能な画面なしスピーカーと報じられる
Anthropic Claude Sonnet 5 と Sonnet 4.6、Opus 4.8 の比較:エージェント型コーディングベンチマーク、API 価格、コストパフォーマンスの検討
Amazon Bedrock AgentCore Gateway を用いたマルチテナントエージェントのためのオンビハーフ・オブ・トークン交換の実装
今日のまとめ
AI日報で今日の重要ニュースをまとめ読み