# Describe an image

Create a reviewed image-to-production-notes Block with owned media and host-controlled vision execution.

Use `runtime: "capability"` with `operation: "image.describe"` when a Block must inspect one image and return plain text. This is the portable boundary for visual analysis: the Block declares its image input, analysis instructions, output, tests, and license; StillMade owns image loading, provider credentials, model/payment selection, approval, accounting, and the retained execution record.

The downloaded SDK includes `examples/describe-image.stillmade.json` and `packages/block-sdk/image-description-example.js`.

```json
{
  "manifest": {
    "schemaVersion": 1,
    "sdkVersion": "0.1.0",
    "id": "example.describe-image",
    "version": "1.0.0",
    "name": "Describe an image",
    "description": "Turn one owned image into concise production-ready visual notes.",
    "kind": "task",
    "runtime": "capability",
    "entry": "src/capability.json",
    "license": "MIT",
    "inputs": {"image": {"type": "image", "primary": true}},
    "outputs": {"description": {"type": "text", "primary": true, "role": "visual_description"}},
    "permissions": {"project": [], "capabilities": ["image.describe"], "network": [], "filesystem": [], "secrets": []},
    "ui": [{"control": "asset", "port": "image"}]
  },
  "capability": {
    "schemaVersion": 1,
    "operation": "image.describe",
    "image": {"$input": "image"},
    "instruction": "Describe only visibly supported subject matter, composition, lighting, color, texture, camera feel and visual style. Return concise production-ready plain text.",
    "maxTokens": 700,
    "output": "description"
  },
  "tests": [{
    "name": "Blue image",
    "input": {"image": {"width": 1, "height": 1, "data": [20, 80, 200, 255]}},
    "expectations": {"description": {"kind": "text", "minLength": 20, "maxLength": 32768, "includes": ["blue"]}}
  }]
}
```

Declare exactly one `image` input (or one `image[]` input to describe or compare one to four images together, in order) and one `text` output. The descriptor contains exactly `schemaVersion`, `operation`, `image`, `instruction`, `maxTokens`, and `output`. `image.$input` names the declared image port. Instructions must contain 1–8,000 characters and `maxTokens` must be 1–4,096. Provider names, endpoints, keys, payment settings, arbitrary URLs, and executable code do not belong in the descriptor.

Fixture inputs may use bounded RGBA pixels for offline contract validation. Real runs use a persistent image reference selected through StillMade. The trusted host requires the referenced media to belong to the signed-in account, reads and bounds the stored bytes, canonicalizes the image to PNG, and sends that image through the exact approved provider request. Block code never receives credentials or storage access.

Tests describe nondeterministic text expectations: `kind:"text"`, ordered `minLength` and `maxLength`, and up to eight literal `includes` phrases. They do not contain fabricated descriptions presented as provider evidence. Offline validation and packaging inspect the contract and report that live review remains required. In StillMade, the creator runs every fixture and a separate sample, reviews the output, and confirms the import.

`prepareCapabilityInvocation` returns `{operation:"image.describe",image,instruction,maxTokens}`. The host returns the named text output through the same capability result, quote, review, project execution, cancellation, failure, and receipt flow used by other hosted Blocks. A completed text record proves the exact package, input, selection, and output passed validation; it does not prove that every sentence is factually correct, so the user reviews the description before using it downstream.
