AI AgentStructured Tool Call

Image Compress AI Integration Guide

Browser-based image compression for AI agents and workflows. Uses Canvas API with quality-aware encoding and no external dependencies.

1. Function Schema

Import directly into Dify, Coze, Cursor, or any tool-calling agent runtime.

Function Schema
{
  "name": "image_compress",
  "description": "Compress images in the browser with quality control and optional resizing.",
  "parameters": {
    "type": "object",
    "properties": {
      "input_base64": {
        "type": "string",
        "description": "Base64-encoded image data. Accepts either a data URI or raw base64."
      },
      "quality": {
        "type": "number",
        "description": "Compression quality from 0.1 to 1.0. Lower means smaller files.",
        "minimum": 0.1,
        "maximum": 1.0,
        "default": 0.8
      },
      "max_width": {
        "type": "integer",
        "description": "Maximum output width in pixels. Use 0 to keep the original width."
      },
      "output_format": {
        "type": "string",
        "enum": ["image/jpeg", "image/png", "image/webp", "image/avif"],
        "description": "Target MIME type for the compressed output.",
        "default": "image/jpeg"
      }
    },
    "required": ["input_base64"]
  }
}

2. System Prompt / SOP

Paste this into your system prompt to keep the generated tool implementation aligned with the contract.

System Prompt SOP
# Task Constraints: Image Compression Module

When implementing browser-side image compression, you MUST follow this SOP.

## Core Prohibitions
- NEVER assume Node image libraries such as sharp or jimp are available.
- NEVER use third-party compression libraries unless they are explicitly imported.
- NEVER return raw pixel buffers in the AI response. Return base64 output instead.

## Standard Implementation
1. Normalize input_base64 by removing the data URI prefix when present.
2. Decode the bytes into a Blob and create an ImageBitmap.
3. If max_width is set and the image is wider than that value, scale proportionally.
4. Draw onto OffscreenCanvas or canvas.
5. Export with convertToBlob() or toBlob() using the requested quality and output_format.
6. Convert the Blob back to a data URI for the response.

## Guardrails
- JPEG and WebP should honor quality.
- PNG should ignore quality because it is lossless in this flow.
- AVIF may be unsupported in some browser sandboxes, so include a fallback path.
- Large images may exhaust memory. Fail fast with a clear error if decoding or rendering fails.

3. Core Script

Modern browser sandbox implementation based on ImageBitmap and OffscreenCanvas. Use it as a drop-in tool-call backend or adaptation template.

Core Script
async function main(args) {
  const {
    input_base64,
    quality = 0.8,
    max_width = 0,
    output_format = "image/jpeg",
  } = args;

  if (!input_base64) {
    return { success: false, result: "", error: "input_base64 is required" };
  }

  try {
    const base64Data = input_base64.replace(/^data:[^;]+;base64,/, "");
    const binaryString = atob(base64Data);
    const bytes = Uint8Array.from(binaryString, (char) => char.charCodeAt(0));
    const blob = new Blob([bytes]);
    const image = await createImageBitmap(blob);

    let { width, height } = image;
    if (max_width > 0 && width > max_width) {
      const ratio = max_width / width;
      width = max_width;
      height = Math.round(height * ratio);
    }

    const canvas = new OffscreenCanvas(width, height);
    const ctx = canvas.getContext("2d");
    if (!ctx) {
      throw new Error("Canvas context unavailable");
    }

    ctx.drawImage(image, 0, 0, width, height);

    let targetFormat = output_format;
    let outputBlob;
    try {
      outputBlob = await canvas.convertToBlob({
        type: targetFormat,
        quality: targetFormat === "image/png" ? undefined : quality,
      });
    } catch {
      targetFormat = "image/webp";
      outputBlob = await canvas.convertToBlob({ type: targetFormat, quality });
    }

    const buffer = await outputBlob.arrayBuffer();
    const outputBase64 = btoa(
      Array.from(new Uint8Array(buffer), (byte) => String.fromCharCode(byte)).join("")
    );

    return {
      success: true,
      result: "data:" + targetFormat + ";base64," + outputBase64,
      mime_type: targetFormat,
      original_size: bytes.length,
      compressed_size: outputBlob.size,
      width,
      height,
    };
  } catch (error) {
    return {
      success: false,
      result: "",
      error: "Compression failed: " + (error instanceof Error ? error.message : String(error)),
    };
  }
}