Adobe Retouch Portraits
A walk-away bulk retouching pipeline for photographers. The user selects their images, optionally adds tweaks, and the agent runs the full batch using Adobe for creativity tools.
Surface note: The default flow uses Adobe's MCP App widgets — the
asset_add_filepicker (Step 1) and theasset_preview_filepreview (Steps 2c and 8). Follow it as written. Only if a widget tool is not available on this surface (e.g. Codex) use the No-widget fallback attached to that step. PresentAskUserQuestionprompts as plain-text labeled options wherever no question widget exists.
Generative AI Policy
This retouching pipeline is fully non-generative by default. The core workflow — auto-straighten, auto-tone, adjustments, presets, blur, and crop — uses no generative AI, and that non-generative pipeline is the only behavior on surfaces that do not permit generative AI (including Claude).
Generative editing runs only where the surface permits it. A surface permits generative AI only when it exposes a generative tool such as image_fill_area (e.g. Codex). Where no such tool is available (e.g. Claude), perform no generative edits of any kind — do not call, attempt, offer, or mention them; run the non-generative pipeline only.
Where generative AI is permitted, it is limited to backgrounds and kept minimal. Only then may image_fill_area correct dust spots, sensor artifacts, or scratches on non-human areas (walls, floors, sky, props), and only when the fix is invisible at normal viewing size — remove a dust spot, not repaint a wall. Never apply generative tools to faces, skin, hair, bodies, or clothing on any surface. Do not alter the scene, remove objects, change the environment, or extend the frame.
If the user asks you to generatively modify a person (e.g. "change her hair color", "make him look younger"), clarify that this skill does not perform generative edits on people — and, on a surface with no generative capability at all, that generative editing isn't available here — then suggest a dedicated generative workflow instead.
Tool Reference (Adobe for creativity connector)
Step 0 - prereq: Initialize Adobe Tools
Call adobe_mandatory_init first. This returns file handling rules and tool routing guidance required for the rest of the workflow.
This also tells you which widgets this surface supports and whether egress is enabled. If asset_add_file and asset_preview_file are available, follow the default flow (Steps 1, 2c, and 8 as written). If one is not available (e.g. Codex), use that step's No-widget fallback. If a tool result carries an importantNote, or the connector injects "Asset Storage & Display" guidance for the current turn, follow it — it overrides the presentation defaults here.
Step 0b: Discover Available Presets
Call image_list_presets immediately after init — before ingestion or user questions. This gives you the full pool of presets available to this user's plan, so you can build a smart, plan-aware preset selection for Step 5.
From the returned list, build a Preset Plan by categorizing presets into four buckets. Use the naming signals below to classify each preset — these are heuristics, not hardcoded names, so apply judgment:
Preset Plan Buckets
1. Adaptive Person Presets — target the subject's body, skin, clothing, or teeth
Naming signals: Adaptive, Subject, Portrait, Person, Skin, Body, Clothes, Outfit, Pop, Warm Pop, Enhance, Teeth, Whiten, Smile, Brighten
Goal: pick 1–3 presets that best boost the human subject. Prefer presets that target skin/body or offer subject-level contrast/warmth lift. Avoid presets that affect only sky or background. Any preset with teeth/smile/whiten signals should be included here so it is available when Whiten Teeth is selected in Step 2.
2. Global Mood / Tone Preset — overall tonal character of the image
Naming signals: Mood, Tone, Warm, Cool, Golden, Cinematic, Film, Natural, Airy, Fade, Matte, Classic
Goal: pick exactly 1 preset. Choose the most portrait-friendly neutral or warm look — avoid heavy stylisation (neon, surreal) unless the user requested an editorial style.
3. Global Toon / Look Preset — stylistic look treatment
Naming signals: Toon, Style, Look, Preset, Vintage, Retro, B&W, Mono, Haze, Glow, Edit, Creative
Goal: pick exactly 1 preset. Choose something complementary to the mood preset — not a duplicate effect. If the mood preset is already cinematic/warm, choose a lighter stylistic touch.
4. Background Blur Preset — softens background to flatter the subject
Naming signals: Blur Background, BG Blur, Bokeh, Depth, Focus, Defocus
Goal: pick exactly 1 blur-background preset. This replaces image_apply_gaussian_blur when the user opts into it.
Fallback strategy:
- If no preset matches a bucket, leave that bucket empty rather than forcing a poor fit.
- If the plan returns no presets at all (403 or empty list), skip Step 5 entirely and note it in the summary: "Adaptive enhancements not available — no presets found on this plan." This is a non-blocking error — all other pipeline steps (tone adjustments, preview gate, full batch) continue exactly as normal. Only Step 5 is skipped.
- Buckets 2 and 3 are global mood/style layers — skip them if you cannot find a clearly portrait-appropriate match. It's better to skip than to apply an ill-fitting preset.
Store the chosen presets as your Preset Plan before Step 2. The user's mood/style selection (collected in Step 2a) may refine which preset is chosen within each bucket — see Step 2a for guidance. Show the final plan to the user in the confirmation message (Step 2).
Step 1: Image Ingestion
Call asset_add_file with no parameters. This renders an interactive UI where
the user can:
- Browse CC storage and select a folder or individual files
- Upload from device (local files)
- In Cowork: select a local folder path directly
Important: asset_add_file returns imageURIs: [] — this is expected and
NOT an error. The actual URIs arrive in the next user message after the
user selects files. Wait for that follow-up before continuing.
After receiving the URIs, call read_widget_context with asset_add_file to resolve them to correct presigned S3 URLs. Use those resolved URLs for all subsequent tool calls — dcx-stage.adobe.io URIs are network-blocked and must be resolved via read_widget_context first.
Always follow this picker path on Claude, even if the user's message already contains a CC URN (e.g. urn:aaid:sc:US:…). CC URNs are not valid presigned URLs — read_widget_context is the only way to resolve them.
Collect the resulting presigned URLs as sourceURIs[] and continue to Step 2a.
No-widget fallback (only if
asset_add_fileis unavailable on this surface, e.g. Codex) — don't ask the user to pick; get the source URIs from where the files are.image_*tools only accept Creative Cloud storage URIs — never raw local paths.The programmatic path uses neither
asset_add_filenorread_widget_context. Collect the resulting presigned CC URLs assourceURIs[].
Step 2a: Mood & Style Selection
Before presenting the pipeline plan, ask the user what mood and style they want for their portraits. This drives which presets are prioritised within the Preset Plan buckets.
If the user's message already states a clear mood/style (e.g. "warm and glowing", "dark and moody", "clean headshots", "editorial"), infer it directly — skip this question and map it using the table below.
If no mood/style is specified, post this message and ask:
Hold — do not proceed to Step 2 until the user replies. (This hold applies only when the question was asked. If mood/style was already inferred from the user's message, skip this hold and proceed directly to Step 2.)
Mood → Preset Plan guidance
Use the selected mood to refine your Preset Plan (built in Step 0b). Within each bucket, prefer presets whose names align with the chosen mood:
If the Preset Plan has multiple candidates in a bucket, pick the one that best matches the chosen mood. If only one preset exists in a bucket, use it regardless of mood.
Step 2: Announce Pipeline + Offer Options
Once the mood/style is confirmed, check whether the user's message already fully specifies their enhancement, tweak, and crop preferences.
If preferences are fully stated upfront (e.g. "retouch with subject pop, no tweaks, crop 1:1"), skip AskUserQuestion entirely and go straight to the confirmation message, then proceed directly to Step 2c (sample preview). The preview gate is mandatory — it runs even when all preferences are stated upfront. Do NOT start the full batch without it. Map their stated preferences using the button→parameter table below.
If preferences are not fully stated (e.g. "please retouch them" with no further detail), post this message first:
Then call AskUserQuestion with these three questions:
Hold processing until the user replies with their selections.
Mapping button selections to parameters
Adaptive enhancements (mapped to Preset Plan built in Step 0b):
- "All" → run all four buckets (Adaptive Person + Mood + Toon + Blur BG), plus Whiten Teeth if face detected
- "Enhance Subject" → apply all presets in the Adaptive Person Presets bucket
- "Mood & Tone" → apply the single preset from the Global Mood / Tone bucket
- "Toon & Style" → apply the single preset from the Global Toon / Look bucket
- "Blur Background" → apply the preset from the Background Blur bucket (skip Step 6 for that image)
- "Whiten Teeth" → apply the Whiten Teeth preset from the Adaptive Person Presets bucket (skip if no face detected; see body detection in Step 5)
- "None" → skip Step 5 entirely
Manual tweaks (all combined into one
image_apply_adjustmentscall in Step 4b — use diagnostic ranges, not hardcoded defaults): - "Recover highlights" →
highlights: -40 to -70(use -40 for mildly blown; -70 for heavily overexposed highlights) - "Lift shadows" →
darks: +30 to +50(positive lifts shadow detail; use +30 for slight lift; +50 for very crushed shadows; prefervibranceto compensate if skin goes dull) - "More contrast" →
contrast: +15 to +30(use +15 for slight pop; +30 only if image is very flat) - "More vibrant" →
vibrance: +15 to +30(prefervibranceoversaturationfor portraits — vibrance protects skin tones) - "Desaturate" →
saturation: -20 to -40(use -20 for muted; -40 for near-monochrome look) - "Blur background — depth-aware bokeh (standard)" →
image_apply_lens_blur→blurRadius: 8(depth-aware, realistic bokeh; skip Step 6 if adaptive blur preset also applied) - "Heavy background blur — stylized gaussian blur" →
image_apply_gaussian_blur→blurRadius: 12, blurTarget: "background"(use only when user explicitly requests heavy/stylized blur; do not combine with Blur Background adaptive preset) - "None" → skip Step 4b entirely Crop:
- "Auto" → landscape →
"4:3", portrait →"3:4", focus:"face" - "1:1 square" →
output: "1:1", focus:"face" - "4:5 portrait" →
output: "4:5", focus:"face" - "16:9 wide" →
output: "16:9", focus:"face"All crop modes usefocus: "face". If no face is detected, fall back tofocus: "subject".
After receiving button selections, confirm the settings back to the user and show the Preset Plan:
Step 2b: Large Batch Warning (N > 5)
Include this in the confirmation when N > 5:
Step 2c: Sample Preview (Before/After on Image 1)
Before running the full batch, process the first image only through the complete pipeline (Steps 3–7) using the confirmed settings. This gives the user a real preview of exactly what will be applied to every image.
To keep the preview fast, first downscale image 1 to a long-edge of 1200px before running it through the pipeline. After confirmation, the final batch (Step 3) processes all images at full resolution — including image 1, which must not be reused from the 1200px preview output.
Store the result as preview_source_url. Use that downscaled URL — not sourceURIs[0] — as the input to Steps 3–7 for the preview pass only.
- Run the full pipeline on
preview_source_urlonly (straighten → tone → tweaks → adaptive → blur → crop). - Call
asset_preview_filewith the original full-res source as "Before" and the processed downscaled output as "After" —asset_preview_filehandles its own thumbnailing so the size difference is invisible to the user:
No-widget fallback (only if
asset_preview_fileis unavailable on this surface, e.g. Codex) — present the two labeled URLs directly in the message:UI clients that render image URLs inline will show both automatically. In Codex or other non-UI agents, download both to the workspace (
curl -L -o before.jpg "<sourceURIs[0]>",curl -L -o after.jpg "<processed_preview_url>") and reference those local paths instead.
- Post this message:
- Call
AskUserQuestionwith a single question:
Processing is fully paused here. Do not start the full batch until the user explicitly selects "Yes". This gate is mandatory and runs every time regardless of how clearly preferences were stated.
If "Yes": proceed to Step 3 for all images (sourceURIs[0…N-1]) at full resolution. Do not reuse the 1200px preview result — it was for confirmation only and must not appear in the final deliverables.
If "No — adjust settings": return to Step 2a to re-collect mood/style if needed, then Step 2 (AskUserQuestion) to re-collect other preferences. Once new settings are confirmed, always repeat the preview — reprocess image 1 with the new settings, show the new before/after, and require explicit confirmation again before proceeding. Never skip the preview gate after an adjustment.
If "Cancel": stop and let the user know they can restart any time.
Step 3: Auto-Straighten (per image)
Loop one image at a time (no batch support):
Output: results[0].outputUrl → collect as straightened_urls[]
On failure: use original URI, note "straighten skipped" for that image.
Step 4: Auto-Tone (per image)
Output: results[0].outputUrl → collect as toned_urls[]
Step 4b: Optional Tone Adjustments (batch)
If the user requested tonal tweaks, combine all selected tweaks into a single image_apply_adjustments call — no need to chain multiple calls:
Omit any parameter the user did not select. One call handles all requested tweaks simultaneously.
Step 5: Adaptive Enhancements (per image, opt-in only)
Only run this step if the user selected one or more adaptive enhancements. The presets to apply come from your Preset Plan built in Step 0b — not hardcoded names.
5a: Subject & Body Detection
Before applying person or teeth presets, call image_select_subject to understand what's in the frame. This drives two decisions: which adaptive person presets to apply, and whether Whiten Teeth is appropriate.
Use the detection results as follows:
- Face detected → include any teeth/smile preset if user selected Whiten Teeth
- Torso / Skin / Hair detected → include body-targeted adaptive person presets (e.g. skin smoothing, body pop)
- Clothing detected → include clothing/outfit-targeted adaptive presets if present in bucket 1
- No subject detected → skip all Adaptive Person Presets for this image; still apply Mood and Toon presets
5b: Apply Preset Plan (in order)
Apply the applicable presets from your Preset Plan in this sequence, chaining each output into the next. Only run buckets the user selected in Step 2 — use the mapping table there to determine which buckets are active for this run. Skip any bucket the user did not select, and skip any preset within an active bucket whose detection condition was not met (see 5a).
Order (run only the buckets that were selected):
- Adaptive Person Presets (bucket 1) — only if "Enhance Subject", "Whiten Teeth", or "All" was selected. Within the bucket: skip body/clothes presets if only a face was detected and no body was found; skip Whiten Teeth if no face detected.
- Global Mood / Tone Preset (bucket 2) — only if "Mood & Tone" or "All" was selected; apply once
- Global Toon / Look Preset (bucket 3) — only if "Toon & Style" or "All" was selected; apply once
- Background Blur Preset (bucket 4) — only if "Blur Background" or "All" was selected; apply once; if applied, skip Step 6 for this image
Output: results[0].outputUrl → chain as input to next preset or Step 6.
On 403 (entitlement): Skip the preset. Note in delivery summary: "[Preset name] was skipped — not included in your Adobe plan." Continue with remaining presets. On other failure: Use previous step's output; note "[preset name] skipped" in summary.
Step 6: Background Blur (per image)
Skip this step entirely if the Background Blur Preset (bucket 4) was applied in Step 5 — the adaptive preset already handled it.
No blur selected: skip this step entirely.
Standard background blur (user selected "Blur background" and adaptive blur preset was not applied):
Prefer image_apply_lens_blur — it produces depth-aware, realistic bokeh by automatically detecting the subject and keeping it sharp:
On failure: fall back to image_apply_gaussian_blur below, note "lens blur unavailable — using gaussian".
Heavy/stylized blur (user explicitly requested "Heavy background blur"):
On failure: use previous step's output, note "blur skipped" for that image.
Output: results[0].outputUrl
Step 7: Crop (per image)
Default behavior:
- Landscape image → crop to
"4:3", focus:"face" - Portrait image → crop to
"3:4", focus:"face" - User-specified ratio (1:1, 4:5, 16:9, etc.) → use that, focus:
"face" - If no face is detected by the crop tool, fall back to
focus: "subject"
These are the final full-resolution deliverables. Collect as final_urls[].
Step 8: Final Preview + Download Links + Firefly Board
Pass the final output URLs directly to asset_preview_file — do NOT run them through image_crop_and_resize first, as that introduces white bars or unwanted cropping. asset_preview_file handles its own thumbnailing correctly.
Call asset_preview_file for every run, regardless of batch size:
No-widget fallback (only if
asset_preview_fileis unavailable on this surface, e.g. Codex) — list the final output URLs directly in the completion message, one entry per image:UI clients that render image URLs inline will display them automatically. In Codex or other non-UI agents, download each to the workspace (
curl -L -o portrait_1.jpg "<final_url_1>", etc.) and reference those local paths instead.
Create Firefly Board
Call the firefly board tool with the final output urls as follows:
Board link handling:
- Extract the returned URL and store as
board_url. - If
board_urlis present and non-empty, include it in the completion message. - If the call fails or returns no URL: note "Firefly Board unavailable" in the summary (retrying does not help).
Then post the completion message. The preview grid is included in every completion message. The board link is included whenever
board_urlwas returned.
If N ≤ 3 — list individual links:
If N > 3 — list all links:
Verbosity Rule
Built for large batches — report only: per-stage start, individual failures (logged once), and the final summary.
- When a pipeline stage begins for the whole batch (e.g. "Straightening [N] images...")
- If an individual image fails (log once, continue)
- Final completion summary with grid + download links
Output Extraction Reference
All pipeline tools return:
Output is read from results[N].outputUrl. On success: false see Error Handling.
Error Handling
Hard Constraints
- Every image in the batch is processed; failures are flagged rather than silently skipped.
- Mood/style is always collected (Step 2a) before the plan is presented — it influences Preset Plan bucket selection.
- The before/after preview gate (Step 2c) is mandatory — the full batch never starts without the user explicitly confirming "Yes". After any settings adjustment, the preview always repeats with the new settings before the batch runs.
- Prefer
vibranceoversaturationfor portrait boosts — vibrance intelligently protects skin tones from oversaturation. - Prefer
image_apply_lens_bluroverimage_apply_gaussian_blurfor background separation — lens blur is depth-aware and produces more realistic bokeh without masking. Use gaussian only for heavy/stylized blur explicitly requested by the user. - Tweak values are diagnostic, not hardcoded — choose values from the reference ranges based on image content;
contrast: +15for mildly flat images,+30only for very flat;highlights: -40for mild blow,-70for severe. - Group/condition awareness — if the batch contains images from clearly different shooting conditions (e.g. mixed indoor/outdoor, or very different exposures), note this in the confirmation message and apply the same user-selected settings to all. For a future enhancement, per-group pipelines could be run separately.
image_apply_auto_toneis called withtype: "cameraRawFilter".- Adaptive enhancements are off by default — only run them if the user explicitly selects them.
- Preset selection is always dynamic: call
image_list_presetsat runtime; never hardcode preset names. - All tonal/colour adjustments use
image_apply_adjustments— the individual tools (image_adjust_highlights,image_adjust_dark_portions,image_adjust_vibrance_and_saturation, etc.) are deprecated and must not be used. - Background blur is handled by the Background Blur preset from the Preset Plan (or
image_apply_lens_blurfor standard blur /image_apply_gaussian_blurfor heavy blur); the adaptive preset and Step 6 are mutually exclusive per image. - Whiten Teeth and body-targeted presets only run when the relevant body part is detected via
image_select_subject. - The pipeline is non-generative by default. Generative tools (
image_fill_area,image_generative_expand) run ONLY where the surface permits generative AI (the tool is available, e.g. Codex) — never on a surface without it (e.g. Claude), and never on people even where permitted. See the Generative AI Policy above. - Never pass a raw local filesystem path to any
image_*tool. Local files must reach Creative Cloud first — selected via theasset_add_filepicker, or (no-widget fallback) staged viaasset_initialize_file_upload→ PUT →asset_finalize_file_upload; only the resulting presigned CC URI is valid. - Push notifications (Slack/email/text) are not available from here; completion is communicated through an in-chat summary.

