Skip to main content
Version: 0.5.0

Iterative Dialogue Pattern

The most important workflow in ClaudusBridge is also the simplest: make a small change → look at it → decide next change → repeat. Most agents misunderstand the watcher as a one-shot "verify at the end" tool. The right model is a continuous conversation:

You make a small change → ask the watcher (or look yourself) "what does it look like now?" → read the prose observation (or the PNG) → make the next small change → ask again → … → finish the user's task with the watcher having narrated every meaningful step.

This guide walks through the pattern with concrete worked examples.


Why iteration beats batching

When you batch many tool calls and verify at the end, every silent failure compounds. A set_widget_anchor that no-ops because the param name was wrong, a Constant3Vector left at default zero, a duplicate Event Tick — none of these break compile. The structural query says "everything is there." The visual reality is broken. By the end of a 20-step build, you have 20 silent issues compounded into one unrecoverable mess.

When you iterate one step at a time and look between every step, every silent failure surfaces immediately. The next step starts from a known-good state. The build either compiles cleanly visually or fails in one identifiable place. Total work is the same; total chaos is dramatically lower.


Cadence: strategic, not constant

The watcher does NOT take screenshots on a timer. It captures only when:

  1. You publish a verification.needed or screenshot.request message
  2. The editor fires a consequential event the watcher subscribed to (actor_spawned, blueprint_compiled, asset_saved, pie_started, pie_stopped, level_changed, actor_deleted)

Match captures to the natural rhythm of the user's task — one capture per meaningful change, not one per micro-edit. A "meaningful change" is something where the visual outcome could plausibly differ from the API success: setting a material parameter, anchoring a widget, wiring a Blueprint pin, spawning an actor, recompiling a material. A "micro-edit" is something where the API result is the visual reality: setting a string variable's default value, renaming a function.


Worked example: build a main menu widget

User asks:

Build me a main menu widget — Play, Options, Quit buttons, centered, with a fade-in animation.

The wrong way (don't do this):

create_widget_blueprint(name="WBP_MainMenu")
add_button_to_widget(name="Play")
add_button_to_widget(name="Options")
add_button_to_widget(name="Quit")
set_widget_anchor(...) # apply to all 3
add_text_block_to_widget(...) # x3
create_widget_animation(name="Fade_In")
add_animation_track(...)
compile_widget_blueprint()
# look at the result for the first time
# discover the buttons stack at (0,0), the text is missing,
# the animation has 0 keyframes, ...

The right way:

PRIMARY: create_widget_blueprint(name="WBP_MainMenu")
publish verification.needed {
tool_call: "create_widget_blueprint WBP_MainMenu",
expected: "a new empty Widget Blueprint asset is open"
}
WATCHER: "WBP_MainMenu open in UMG editor; empty Canvas Panel root, no
children, hierarchy panel shows only [CanvasPanel]."

PRIMARY: add_button_to_widget(WBP_MainMenu, parent=Canvas, name="Play")
publish verification.needed {
tool_call: "add_button_to_widget Play",
expected: "Play button visible in the canvas, default style"
}
WATCHER: "Play button at top-left of canvas, white default style, label
empty. Hierarchy now shows [CanvasPanel > Button_Play]."

PRIMARY: set_widget_anchor(Play, anchor="center")
add_text_block_to_widget(Play, text="Play")
publish verification.needed {...expected: button centered, reads Play...}
WATCHER: "Play button now centered in the canvas, displays 'Play' in white
text. Hierarchy correctly nests [CanvasPanel > Button_Play >
TextBlock_PlayLabel]."

…and so on for Options, Quit, then the fade-in animation. Each step is
ONE small change followed by a verification round-trip.

If a step silently no-ops (e.g. set_widget_anchor with the wrong param name), the watcher's next observation says "Play button still at top-left" and the primary catches it on the very next turn instead of compounding the error into 10 other steps.


Worked example: build a holographic material

User asks:

Make a holographic-looking material with pulsing emission.

PRIMARY: create_material(name="M_Holo")
open_asset_editor(asset_path="/Game/M_Holo")
capture (via cb capture or watcher screenshot.request)
WATCHER: "M_Holo open in material editor. Preview sphere is dull gray
(default). Material settings: blend mode Opaque, shading model
Default Lit. Graph is empty except for the output node."

PRIMARY: create_material_expression(material=M_Holo,
expression_type="MaterialExpressionTime")
create_material_expression(material=M_Holo,
expression_type="MaterialExpressionSine")
connect_material_expressions(from=Time, to=Sine.input)
capture
WATCHER: "Two new nodes visible: Time (top-right) wired to Sine. Sine
output is unconnected. Preview sphere unchanged (still dull gray)
because nothing reaches Emissive Color yet."

PRIMARY: create_material_expression(M_Holo, "MaterialExpressionConstant",
value=2.0)
create_material_expression(M_Holo, "MaterialExpressionMultiply")
connect_material_expressions(Sine.output → Multiply.A)
connect_material_expressions(Constant.output → Multiply.B)
connect_material_expressions(Multiply.output → output.EmissiveColor)
set_material_properties(blend_mode=Translucent, shading_model=Unlit)
recompile_material()
capture
WATCHER: "After recompile_material returned success, preview sphere is
STILL dull gray. The graph shows the chain wired correctly
(Time → Sine → Multiply, Constant=2 → Multiply, Multiply →
Emissive), but the preview hasn't refreshed. CLICK APPLY in the
toolbar to push the new shader to preview."

PRIMARY: (clicks Apply via mouse-event injection or asks user)
capture
WATCHER: "Preview sphere now pulsing white-to-bright-white at ~1Hz.
Emissive chain is firing correctly. Material visually matches
the holographic-pulsing intent."

The Apply-button quirk would be invisible without the iterative cadence. With it, the watcher catches the divergence on the very first post-recompile capture and surfaces the action the primary needs to take.


Framing the shot

When the change is on a specific actor, asset, or aspect, include framing guidance in the verification payload — the watcher will move the camera, change view mode, or toggle show flags BEFORE capturing so you actually see the relevant subject.

publish verification.needed {
tool_call: "spawn_basic_shape Sphere at [420,69,180]",
expected: "a blue sphere visible at world location 420,69,180",
framing: { focus_actor: "Parity_AB_Sphere", view_mode: "lit" }
}

Supported framing fields (the watcher reads any of these):

FieldWhat it triggers
focus_actor: "<label>"focus_viewport_on_actor to center the camera
view_mode: "lit"|"unlit"|"wireframe"|"collision"|...set_view_mode
show_flags: { Bounds: true, Collision: true, ... }set_show_flag for each
viewport_type: "perspective"|"top"|"front"|...set_viewport_type
open_asset: "/Game/<path>"open_asset_editor to bring an asset window forward

The watcher applies these BEFORE capturing, then captures, then optionally restores the view state (e.g. turns off show_flags.Collision after the capture).


Agency boundary — eyes vs hands

The watcher MAY adjust the view (camera, view mode, show flags, viewport type, asset window focus) freely to give better ground truth. These are purely visual and don't change saved project state.

The watcher MUST NOT mutate world content (spawn / delete / set_actor_property, BP / material / widget content edits, save / build, start / stop PIE) without explicit primary delegation on a delegate.<domain> channel. By default the watcher is eyes, not hands. Content mutations are the primary's job; the watcher confirms or rejects what the primary did.

If the primary explicitly hands work to the watcher (channel: "delegate.material" with payload describing what to change), the watcher MAY perform that mutation, then publishes task.complete with the result.


Reading the watcher's reports

The watcher publishes plain-text observations on these channels (drained from primary's queue between user messages):

ChannelTriggerRead
watcher.observationAutonomous report on a consequential eventThe watcher saw something happen and decided you should know
verification.confirmedYour verification.needed produced the expected visualYour last tool call achieved its visual intent
verification.rejectedVisual disagrees with expectedThe tool said success but the editor disagrees — read payload.observation carefully
screenshot.responseAnswer to your screenshot.requestPlain-text description of what's currently visible

Read data.payload.observation (plain text) — that's the watcher's ground-truth analysis of the captured image. You do NOT need to read the PNG yourself; the watcher already analyzed it for you. (Unless you're using cb capture directly, in which case you ARE the watcher for that round-trip.)


When direct capture beats sub-agent watcher

For one-shot "what does this look like now?" checks, use cb capture and view the PNG yourself with multimodal vision. Round-trip is ~3-5 seconds — faster than spawning a sub-agent.

For multi-event autonomous monitoring (consequential editor events, iterative dialogue across many edits), the sub-agent watcher is right — it idles cheaply and reports curated observations without you having to ask.

ScenarioPath
"I just made a change, did it work?"cb capture + view PNG yourself
"I'll be doing 30 minutes of UMG work, narrate the consequential changes"Sub-agent watcher with the canonical prompt
"Test parity across both browser extensions"Dual sub-agent watchers (Claude in Chrome + Codex bridge)
"Verify a high-stakes lighting bake actually applied"Sub-agent watcher + verification.needed with framing

Cadence anti-patterns

Avoid these:

Anti-patternWhy it failsFix
20 tool calls then 1 verificationAll errors compound; visual diff is unreadableOne verification per meaningful change
Capture only at the endSilent failures invisible until too lateCapture between every change
Trust API success without visual confirmTools can no-op silentlyVisual verification is the only ground truth
Capture every micro-editWastes tokens and timeSkip captures for edits where API result IS the visual reality (string variable defaults, function renames)

Next steps