Skip to content

fix(server): make AgentConfig.synthesize nullable Boolean (unblocks Suite16)#242

Merged
v1r3n merged 1 commit into
mainfrom
fix/main-synthesize-restore
May 16, 2026
Merged

fix(server): make AgentConfig.synthesize nullable Boolean (unblocks Suite16)#242
v1r3n merged 1 commit into
mainfrom
fix/main-synthesize-restore

Conversation

@v1r3n

@v1r3n v1r3n commented May 16, 2026

Copy link
Copy Markdown
Contributor

Summary

Cherry-picks the relevant slice of PR #238's commit 6fb791a4 to unblock java-e2e > Suite16Synthesize > test_handoff_default_has_final_task on main.

What's wrong on main

AgentConfig.synthesize is a primitive boolean with @Builder.Default = true. Lombok generates a getter that always returns a value, and Jackson with @JsonInclude(NON_NULL) can't omit a primitive — so the field always serializes:

agentDef = {..., "synthesize": true}

even when the caller never set it. Suite16Synthesize.test_handoff_default_has_final_task (Suite16Synthesize.java:89) asserts:

assertFalse(agentDef.containsKey("synthesize"),
    "[default handoff] agentDef should NOT contain 'synthesize' when default.");

→ fails on every run.

Fix

Change the field to private Boolean synthesize; (nullable, no @Builder.Default) and add an explicit isSynthesize() that treats null as true. @JsonInclude(NON_NULL) now keeps the field out of serialized output when callers leave it unset; explicit synthesize=false still round-trips through agentDef.

All three MultiAgentCompiler call sites already consume config.isSynthesize() — behavior preserved.

Test plan

  • ./gradlew test (server) → BUILD SUCCESSFUL.
  • ./gradlew test -Pe2e (sdk/java) on a server jar built from this branch → 178 / 178 pass (was 177 / 178 with Suite16Synthesize.test_handoff_default_has_final_task failing).

Same fix has been on PR #238 since 6fb791a4; pulling it forward here so main's java-e2e gate is green now, rather than waiting for the bigger PAC/PAE branch to land.

The PAC/PAE commit (acbde7d) accidentally removed:

  * ``AgentConfig.synthesize`` (the field that gated the final-LLM
    synthesis step on HANDOFF / ROUTER / SWARM strategies, added by
    PR #189);
  * The ``if (config.isSynthesize()) tasks.add(finalLlm);`` guards at
    the three call sites in MultiAgentCompiler.

Result: ``synthesize=false`` was silently ignored — the SDKs serialized
the flag but the server's Jackson dropped it on deserialise (no field),
and the workflow always emitted the ``_final`` LLM_CHAT_COMPLETE task.
The Java ``Suite16Synthesize`` e2e suite caught this once it started
running in CI (3 / 4 tests failing).

Restore in three pieces:

* ``AgentConfig.synthesize`` — modelled as nullable ``Boolean`` (not
  primitive + Builder.Default) so ``@JsonInclude(NON_NULL)`` keeps the
  field out of serialized output when callers leave it unset. The Java
  SDK's ``Suite16Synthesize`` test asserts the agentDef metadata MUST
  NOT contain ``synthesize`` when the flag is at its default — a
  primitive-with-default would always have emitted it as ``true`` and
  failed that contract.
* ``AgentConfig.isSynthesize()`` — manual getter treating ``null`` as
  ``true`` so existing compiler call sites read the right default.
* ``MultiAgentCompiler`` — restore the ``isSynthesize()`` guards at all
  three sites (handoff at ~390, router at ~981, swarm at ~1271) so
  ``synthesize=false`` skips the ``_final`` task and routes
  ``${workflow.variables.conversation}`` directly to the workflow's
  ``result`` output instead of the missing ``_final.output.result``.

* ``./gradlew test`` (server) → 570 / 570 pass.
* ``./gradlew test -Pe2e --tests Suite16Synthesize`` (sdk/java) →
  4 / 4 pass against PR #238 server.
@v1r3n v1r3n merged commit 0f45a47 into main May 16, 2026
9 checks passed
@v1r3n v1r3n deleted the fix/main-synthesize-restore branch May 16, 2026 18:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant