Skip to content

feat(groq): built-in-tools request fork + boundary gating (#69 S4)#72

Merged
stackbilt-admin merged 3 commits into
mainfrom
feat/groq-builtin-tools-adapter
May 29, 2026
Merged

feat(groq): built-in-tools request fork + boundary gating (#69 S4)#72
stackbilt-admin merged 3 commits into
mainfrom
feat/groq-builtin-tools-adapter

Conversation

@stackbilt-admin
Copy link
Copy Markdown
Member

Implements S4 of the Groq built-in-tools sprint (#69), on top of the merged S3 catalog (#71).

What

Forks the Groq adapter's request shape by model family and gates built-in tools at the boundary.

Model family Wire shape Vocabulary
groq/compound, groq/compound-mini compound_custom.tools.enabled_tools: [...] normalized identifiers verbatim (compound's vocabulary is the normalized set)
openai/gpt-oss-120b OpenAI-style tools: [{ type }], merged onto the same array as function tools translated — web_searchbrowser_search

Gating reuses the catalog — no drift

The capability gate calls modelSupportsBuiltInTools(model, 'groq', tool.type) (the accessor S3 built) as the single source of truth, rather than a duplicate capability set in the adapter. Only the wire-translation map (web_searchbrowser_search) is local, since spelling isn't a catalog concern. The enforcement point is still the adapter (satisfies the issue review's "gating belongs in the adapter, not catalog-only" — the accessor takes (model, provider) explicitly, so pinned models that bypass routing are still gated).

  • Unsupported (model, tool)ConfigurationError naming the capable models and, for gpt-oss, its supported subset (web_search, code_interpreter).
  • Gate-passed-but-unmapped tool → explicit internal error rather than emitting {type: undefined}.

Also required — the models array

base.validateRequest rejects any pinned model not in the provider's models list before formatRequest runs, so model: 'groq/compound' would have thrown without this. Added both compound models there + matching getModelCapabilities() entries (token costs estimated; built-in surcharges not token-tracked, per issue scope).

Deliberately not touched

  • TOOL_CAPABLE_MODELS — compound's function-tool support is unverified from the S0 spike, so the conservative reject stands (built-in tools are a separate, gated path).
  • GROQ_RESPONSE_SCHEMA — response parsing is S5. Confirmed validateSchema ignores undeclared fields, so the unchanged schema already passes a real executed_tools response.

Tests

typecheck clean; 398 pass (+7 new): compound fork shape, five-tool verbatim passthrough, gpt-oss translation, function+built-in merge on one array, function-only-model rejection (names capable models), unsupported-tool-on-gpt-oss rejection (names subset), pinned-groq/compound accepted through validateRequest.

Next: S5 — parse executed_tools[].search_results.resultsmetadata.builtInToolResults, extend GROQ_RESPONSE_SCHEMA.

🤖 Generated with Claude Code

Forks the Groq adapter's request shape by model family and gates built-in
tools at the boundary:

- compound systems (groq/compound, groq/compound-mini) → built-in tools on
  compound_custom.tools.enabled_tools, taking the normalized identifiers
  verbatim (Groq's compound vocabulary IS our normalized set).
- openai/gpt-oss-120b → OpenAI-style tools:[{type}] entries merged onto the
  same array as function tools, translated to gpt-oss's native vocabulary
  (web_search → browser_search).

Gating reuses the catalog accessor modelSupportsBuiltInTools(model,'groq',
tool.type) as the single source of truth — no duplicate capability set in
the adapter, so it can't drift from the S3 catalog entries. Only the
wire-translation map (web_search→browser_search) is local, since spelling
isn't a catalog concern. Unsupported (model, tool) pairs throw a
ConfigurationError naming the capable models and, for gpt-oss, its supported
subset. A gate-passed-but-unmapped tool throws an explicit internal error
rather than emitting {type: undefined}.

Also required: groq/compound + groq/compound-mini added to the adapter's
`models` array — base.validateRequest rejects any pinned model not listed
there before formatRequest runs, so a pinned compound request would 400
otherwise. Added matching getModelCapabilities entries (token costs
estimated; built-in surcharges not token-tracked, per issue scope).

Not touched: TOOL_CAPABLE_MODELS (compound function-tool support is
unverified from the S0 spike — conservative reject stands) and
GROQ_RESPONSE_SCHEMA (response parsing is S5; validateSchema already ignores
the undeclared executed_tools field, so real compound traffic passes).

typecheck clean; 398 tests pass (+7 groq adapter tests: compound fork,
five-tool passthrough, gpt-oss translation, function+built-in merge,
function-only rejection, unsupported-tool rejection, pinned-model accept).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
stackbilt-admin and others added 2 commits May 28, 2026 20:21
The function-only-model rejection test called generateResponse twice; the
first ConfigurationError (thrown inside executeWithResiliency) accumulates a
circuit-breaker failure, so the second call could throw a breaker error
instead of the ConfigurationError. Assert both expectations against one
invocation. Surfaced by CI; local runs masked the timing dependence.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ase (#69)

OSS package — docs travel with the feature. Covers what's shipped through
S4 (request side + gating), accurately scoping structured result surfacing
(metadata.builtInToolResults) as a follow-up:

- README: Features bullet, Groq providers-table row, MODELS.GROQ_COMPOUND/_MINI
  constants, and a "Built-in Tools (Server-Side)" section (normalized
  identifiers, per-model wire-shape table, routing/provenance/cost notes).
- CHANGELOG: [Unreleased] section enumerating the builtInTools field, the
  BuiltInTool* types, supportsBuiltInTools, modelSupportsBuiltInTools, the
  Compound catalog entries, the RESEARCH use case, and the capability-aware
  routing + request fork.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@stackbilt-admin stackbilt-admin merged commit 173ed3d into main May 29, 2026
2 checks passed
@stackbilt-admin stackbilt-admin deleted the feat/groq-builtin-tools-adapter branch May 31, 2026 10:12
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