Skip to content
2 min read · 432 words

Advisories & Unconfirmed Recipes

The validation battery distinguishes between hard protocol invariants (which break turn execution if violated) and vendor best-practice advisories (which represent soft recommendations or hygiene practices).

Treating a vendor's soft "please don't do this" as a fatal rejection is how a validation library becomes more annoying than the problems it was built to solve. The advisory tier exists specifically so this battery never pretends a suggestion is an invariant just because treating everything as an error is easier to code.

Non-Blocking Advisories

Advisory rules represent vendor recommendations or soft deprecations, not fatal protocol violations.

Examples include:

  • stale_thinking_advisory (used in gemma-4): Recommends pruning thought content predating the latest user turn.
  • thought_signature_advisory (used in gemini-2-5): Notes the absence of a thought signature without blocking execution.

How the Guard Handles Advisories

When an advisory rule triggers:

  1. It is recorded in OrderingGuardResult.advisories under __orderingGuardLastResult on ctx.stash.
  2. It is never added to unrepaired violations.
  3. It will never trigger ctx.nack(), ctx.abort(), or throw an exception, in either enforce or mutate mode.

Selectively Disabling Advisories

If you intentionally deviate from a vendor's default hygiene recommendation (for example, setting Gemma 4's preserve_thinking flag to maintain long-term reasoning history), you can silence the rule by ID using disableAdvisoryRuleIds:

ts
import { orderingGuardDispatchMiddleware } from '@nhtio/adk/batteries/validation'

const middleware = orderingGuardDispatchMiddleware({
  profiles: ['gemma-4'],
  // Silences the Gemma 4 stale thinking advisory; skips evaluation entirely
  disableAdvisoryRuleIds: ['stale-thinking-gemma4'],
})

disableAdvisoryRuleIds only suppresses rules with severity: 'advisory' or rule type staleContentAdvisory; it cannot suppress blocking validation rules.

Unconfirmed & Placeholder Recipes

Not all model vendors publish complete specifications for their chat templates, tool calling roles, and ordering constraints.

For the models below, this battery is guessing based on the closest documented analog. We do this because the alternative — shipping nothing — leaves those model keys completely unresolvable, while shipping a guess dressed up as certainty would be far worse.

The following family recipes in FAMILY_RECIPES are unconfirmed baseline guesses seeded from openai_shape_baseline:

  • bytedance-seed (Doubao / Seed models on Volcano Engine Ark)
  • muse-spark (Meta Superintelligence Labs Muse Spark)
  • muse-glimmer (Meta Muse Glimmer)

These profiles are registered in the family catalog so that model keys resolve consistently. But do not confuse registration with verification: do not rely on these recipes in enforce mode in production without testing against upstream endpoints first. If upstream rejects a payload shape we guessed at, that's not a bug in your agent — it's the inevitable cost of vendor documentation voids.

See Also