enekui
AI  ·  7 min

Build a serverless image editing agent with Amazon Bedrock AgentCore harness

AWS published a detailed walkthrough this week showing how to build a production-grade image editing agent using Bedrock's AgentCore harness. The solution lets users upload a photo, describe edits in plain English ("make the sky more dramatic", "remove the person on the left"), and get results in seconds—all serverless, no custom orchestration code.

The full post went live on the AWS Machine Learning blog and includes a complete CDK stack you can deploy in one command. If you've been waiting for a concrete Bedrock Agents example that isn't a chatbot demo, this is it.

What AgentCore harness actually does

Bedrock Agents launched with a managed orchestration layer, but many teams hit friction when they needed custom logic or wanted to run the agent outside AWS's hosted UI. AgentCore harness solves this: it's the same orchestration engine Bedrock uses internally, packaged as a library you control.

You define tools (Lambda functions), point the harness at a foundation model (Claude 3.5 Sonnet in this example), and the harness handles: - Parsing user intent from natural language. - Deciding which tool(s) to call and in what order. - Passing parameters extracted from the prompt. - Returning structured results.

The image editing agent in the post uses three tools: 1. Resize – changes dimensions, maintains aspect ratio. 2. Crop – extracts a region by coordinates. 3. Adjust brightness/contrast – applies PIL filters.

All three are Python Lambda functions. The harness orchestrates them based on the user's English description. No if/else chains, no regex parsing prompts.

Architecture: what you actually deploy

The CDK stack provisions: - S3 buckets (encrypted at rest) for uploads and processed images. - Lambda functions for the three editing tools + the agent runtime. - API Gateway with Cognito authentication. - React frontend (static site on S3 + CloudFront).

The agent Lambda receives the user prompt and image S3 key, invokes AgentCore harness with the model and tool definitions, and returns the edited image URL. The frontend polls for completion (the post uses a simple status endpoint; you'd add WebSockets or EventBridge for production scale).

Total infrastructure: ~15 resources. Deploy time under 10 minutes [per AWS]. The post includes the full CDK code in TypeScript.

What this means for your SMB

If you're running a SaaS with user-generated content—property listings, e-commerce product photos, design tools—this pattern is immediately useful. Before Bedrock Agents, you'd either: - Build a rigid UI with sliders and dropdowns (high dev cost, poor UX). - Integrate a third-party API (Cloudinary, Imgix) and pay per transformation.

Now you can let users describe edits in natural language and handle it serverless on your own AWS account. The cost model is: - Bedrock inference: charged per input/output token. Claude 3.5 Sonnet is $3 per million input tokens, $15 per million output [per AWS pricing]. A typical image edit prompt is ~200 tokens in, ~100 tokens out, so under $0.001 per request. - Lambda: the three tool functions run for ~500ms each. At $0.0000166667 per GB-second, you're paying cents per thousand edits. - S3 + transfer: negligible unless you're serving millions of images/month.

For an SMB doing 10,000 edits/month, you're looking at low double-digit euros in Bedrock costs, single-digit in Lambda. Compare that to Cloudinary's $99/month starter plan (25GB bandwidth, 25k transformations).

The real win isn't cost—it's flexibility. You control the tools. If you need "remove background" or "apply brand watermark", you add a Lambda function and register it with the harness. No API limits, no vendor lock-in on the transformation logic.

How we'd apply it at Enekui

We'd use this pattern for a client in hospitality tech (vacation rental platform, ~€6M revenue, 3-person eng team). They currently pay Cloudinary €180/month and still get support tickets when hosts want edits Cloudinary doesn't offer ("make the pool water bluer", "brighten the kitchen without washing out the countertops").

Our approach: 1. Deploy the CDK stack as-is to their existing AWS account (they're already on Lambda + S3). 2. Replace the three demo tools with: - Background removal (rembg library in Lambda, 2GB memory). - Selective colour boost (PIL with HSV masking). - Watermark overlay (their logo, positioned by the agent based on image composition). 3. Swap Claude 3.5 Sonnet for Haiku in the harness config (faster, cheaper for simple edits; Sonnet only for complex multi-step requests). 4. Add a DynamoDB table to log prompts and tool calls—helps us tune the tool descriptions (the harness uses these to decide which tool to invoke).

Infrastructure cost: ~€40/month at their current 8k edits/month. We'd keep Cloudinary as a fallback for the first month, then cut it. Total dev time: 2 weeks (1 week tools + integration, 1 week testing + deployment).

Code: registering a tool with AgentCore

Here's how you define a tool in Python (simplified from the post):

from bedrock_agent_core import Tool, ToolParameter

resize_tool = Tool(
    name="resize_image",
    description="Resize an image to specified dimensions while maintaining aspect ratio",
    parameters=[
        ToolParameter(
            name="width",
            type="integer",
            description="Target width in pixels",
            required=True
        ),
        ToolParameter(
            name="height",
            type="integer",
            description="Target height in pixels",
            required=True
        )
    ],
    handler=lambda params: resize_image_lambda(params)
)

The description fields are critical—the model uses them to decide when to call the tool. Be specific: "Resize to exact dimensions" vs "Resize maintaining aspect ratio" changes behaviour.

You then pass the tool list to the harness:

from bedrock_agent_core import AgentCore

agent = AgentCore(
    model_id="anthropic.claude-3-5-sonnet-20241022-v2:0",
    tools=[resize_tool, crop_tool, adjust_tool]
)

response = agent.invoke(
    prompt="Make this image 800 pixels wide and increase the contrast",
    context={"image_key": "uploads/photo123.jpg"}
)

The harness parses the prompt, calls resize_tool with width=800 (infers height from aspect ratio), then calls adjust_tool with contrast parameters. You get back the S3 key of the final image.

Gotchas we'd watch for

  1. Tool description quality: if your descriptions are vague, the model guesses wrong. We'd A/B test descriptions in the first week (log every invocation, review misrouted calls).
  2. Cold starts: Lambda with PIL + rembg takes 3-5 seconds cold. Provision 1-2 warm instances or accept the latency (for async workflows, it's fine).
  3. Image size limits: Lambda has a 6MB response payload limit. For images >6MB, write to S3 and return the key, don't return the bytes inline.
  4. Bedrock throttling: the post doesn't mention this, but Bedrock has soft limits (requests/minute varies by model and region). For high-traffic SMBs, request a limit increase upfront.

When this isn't the right fit

If your edits are deterministic (always crop to 16:9, always apply the same filter), don't use an agent—just call the Lambda directly. Agents add latency (model inference) and cost. Use them when the user intent is ambiguous or multi-step.

Also, if you need real-time previews (user drags a slider, sees the result instantly), this won't work—Bedrock inference is 1-3 seconds. Stick with client-side libraries (canvas API, WebAssembly) for interactive tools.

Want help shipping this?

We run a 2-week cloud diagnosis (€2,900) where we audit your current AWS setup, identify one high-impact automation (like replacing a third-party API with a Bedrock agent), and deliver a working proof-of-concept with Terraform. If you're spending >€150/month on image processing APIs and have 10k+ transformations/month, this pays for itself in 6 months. Book a 30-minute intro call.

Fuentes