Skip to content

feat(toolschema): fail-open tool-catalog compressor preserving the selection surface - #83

Merged
Patel230 merged 3 commits into
mainfrom
feat/toolschema-shrink
Aug 23, 2026
Merged

feat(toolschema): fail-open tool-catalog compressor preserving the selection surface#83
Patel230 merged 3 commits into
mainfrom
feat/toolschema-shrink

Conversation

@Patel230

Copy link
Copy Markdown
Contributor

Summary

A large MCP/OpenAI tool catalog is paid on every request. ShrinkToolCatalog cuts that cost while preserving, byte-for-byte, everything a model needs to select a tool and construct valid arguments.

Contract

Kept exactly: tool names, parameter names, type, enum, required, default, const, $ref targets, format.
Dropped: $schema/$id/title/examples/$comment/x-* annotations.
Reduced (lossy, model-visible): descriptions >600 bytes reduce to lead sentence + every constraint-marker sentence (must/cannot/required/at most/max/format/ISO/RFC/rejected…). Shorter descriptions are never touched — over-keep is the rule.

Fail-open everywhere: malformed input, per-tool parse errors, and not-smaller results all pass through unchanged. LintToolCatalog reports per-tool reductions without committing.

Correctness boundary

TestShrinkKeepsSelectionSurfaceIdentical proves the structural selection surface (names/types/enums/required/defaults/constraints) survives identically via profile equality. Behavioral same-tool selection is model-visible and remains inferred.

Verification

8 new tests; full suite green across all 15 packages; vet clean.

…lection surface

ShrinkToolCatalog reduces OpenAI-style function catalogs that are paid on
every request: annotation metadata ($schema/$id/title/examples/$comment/
x-*) is dropped; long descriptions reduce to their lead sentence plus every
constraint-marker sentence (must/required/max/format/ISO/RFC/...); leaf
property descriptions get the same treatment past a 600-byte over-keep
threshold.

Kept byte-for-byte: tool names, parameter names, types, enums, required,
default, const, $ref targets, format. Correctness boundary is enforced by a
selection-profile equality test proving the structural selection surface
survives identically; behavioral same-tool selection remains model-visible
and inferred. Over-keep is the rule: short descriptions are never touched so
constraints phrased without recognized markers survive whole.

Fail-open everywhere: malformed input, per-tool parse errors, and
not-smaller results all pass through unchanged claiming nothing.
LintToolCatalog reports per-tool reductions without committing.
@Patel230
Patel230 merged commit a7c4b99 into main Aug 23, 2026
20 checks passed
@Patel230
Patel230 deleted the feat/toolschema-shrink branch August 23, 2026 02:49
Patel230 added a commit to GrayCodeAI/hawk that referenced this pull request Aug 23, 2026
Wires tok's new toolschema compressor (GrayCodeAI/tok#83) into the
outgoing request path behind HAWK_TOOL_SHRINK=1 (default off, request
bytes unchanged).

At ChatService.BuildOptions the tool list converts to the OpenAI
function-catalog wire shape, shrinks, and converts back. Fail-open
guarantees: any marshal/unmarshal error, tool-count drift, or name
mismatch at any position returns the original list untouched; disabled
or not-smaller catalogs are no-ops. When compression lands, the exact
pre-shrink catalog persists under state/tool-catalog-originals/<sha>.json
keyed by content hash for recovery and diffing, and a one-time info log
reports before/after byte counts.

Facades extended: internal/token aliases tok.ToolShrinkStats and exposes
ShrinkToolCatalog/LintToolCatalog; internal/engine/token re-exports.

Submodule bump includes tok#82 invariants (already wired separately on
feat/invariant-markers; this branch stacks on it for the pointer).

New tests: disabled-by-default no-op, enabled reduction with name/
constraint/required preservation through BuildOptions, and recovery-file
persistence.
Patel230 added a commit to GrayCodeAI/hawk that referenced this pull request Aug 23, 2026
#236)

* feat(tools): opt-in tool-catalog shrink via tok; bump submodule to #83

Wires tok's new toolschema compressor (GrayCodeAI/tok#83) into the
outgoing request path behind HAWK_TOOL_SHRINK=1 (default off, request
bytes unchanged).

At ChatService.BuildOptions the tool list converts to the OpenAI
function-catalog wire shape, shrinks, and converts back. Fail-open
guarantees: any marshal/unmarshal error, tool-count drift, or name
mismatch at any position returns the original list untouched; disabled
or not-smaller catalogs are no-ops. When compression lands, the exact
pre-shrink catalog persists under state/tool-catalog-originals/<sha>.json
keyed by content hash for recovery and diffing, and a one-time info log
reports before/after byte counts.

Facades extended: internal/token aliases tok.ToolShrinkStats and exposes
ShrinkToolCatalog/LintToolCatalog; internal/engine/token re-exports.

Submodule bump includes tok#82 invariants (already wired separately on
feat/invariant-markers; this branch stacks on it for the pointer).

New tests: disabled-by-default no-op, enabled reduction with name/
constraint/required preservation through BuildOptions, and recovery-file
persistence.

* fix(deps): pin tok module to #83 (a7c4b99d) for submodule parity

Rebase onto post-#235 main; update the tok require directive to the
toolschema merge and align the gitlink, satisfying release parity.
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