Skip to content

sanitize responses function call names - #10344

Merged
alexhancock merged 1 commit into
mainfrom
fix/provider-safe-agent-names
Jul 10, 2026
Merged

sanitize responses function call names#10344
alexhancock merged 1 commit into
mainfrom
fix/provider-safe-agent-names

Conversation

@tulsi-builder

Copy link
Copy Markdown
Collaborator

Category: fix
User Impact: Users can mention agents with spaces or symbols in their names without OpenAI Responses requests failing before the agent can respond.
Problem: Replayed function calls in the OpenAI Responses formatter forwarded tool names exactly as stored in conversation history. Agent- or frontend-derived names like Crack Catcher can include spaces or @, which violates OpenAI's input[].name pattern and causes a 400 response.
Solution: Reuse the existing OpenAI function-name sanitizer when serializing Responses API function_call items, matching the chat-completions formatter behavior and keeping display names unaffected.

File changes

crates/goose-provider-types/src/formats/openai_responses.rs
Sanitizes replayed regular and frontend function-call names before placing them in the Responses API input array. Adds a regression test covering agent-style names with spaces and mention prefixes.

Tests:

  • cargo test -p goose-provider-types test_responses_request_sanitizes_replayed_function_call_names
  • cargo fmt --check

@tulsi-builder
tulsi-builder force-pushed the fix/provider-safe-agent-names branch from 9f57190 to 69c1526 Compare July 10, 2026 15:23
@tulsi-builder

Copy link
Copy Markdown
Collaborator Author

🤖 Rebased this onto current main after the Berd pin was overwritten by squareup/berd#779. We need this merged upstream first so Berd can update goose-backend.lock.json to a Goose main commit rather than pinning to this feature branch.

@alexhancock
alexhancock added this pull request to the merge queue Jul 10, 2026
Merged via the queue into main with commit 9cec9f2 Jul 10, 2026
24 checks passed
@alexhancock
alexhancock deleted the fix/provider-safe-agent-names branch July 10, 2026 16:14
chadac added a commit to chadac/scooter that referenced this pull request Jul 21, 2026
…ception) (#141)

* fix(goose): patch Bedrock tool-name sanitization (resume ValidationException)

Carry a downstream cargoPatches patch on goose-cli that sanitizes Bedrock tool
names to [a-zA-Z0-9_-]+.

The bug: goose surfaces an MCP tool's display name ("<Extension>: <Title Case>",
e.g. "Scooter-env: Slack Respond") into a message's tool_call.name. On conversation
RESUME, goose reloads that display-formatted name from its sessions.db and serializes
it into the Bedrock converse request's toolUse.name, which Bedrock rejects:

  ValidationException: ... toolUse.name failed to satisfy constraint: Member must
  satisfy regular expression pattern: [a-zA-Z0-9_-]+

Once the invalid name enters the replayed history, every subsequent turn fails —
the conversation is permanently wedged (only editing goose's sessions.db recovers
it). Affects any conversation that used MCP tools AND was resumed.

The agent-host never builds the Bedrock request (goose owns the provider end-to-end),
so the fix is downstream in goose. The patch sanitizes at the three outbound sites
that must agree (the tool definition in toolConfig + both ToolUseBlock builders) and
keeps a lossless sanitized->original map so the name Bedrock echoes back is restored
for MCP dispatch. toolResult pairs by tool_use_id, not name, so it's untouched. The
sanitizer is idempotent, so an already-valid name (scooter-env__slack_respond) is a
free identity round-trip.

- pkgs/goose/bedrock-tool-name-sanitize.patch: the sanitizer + 4 call-site swaps +
  2 Rust round-trip unit tests (run in-build; nixpkgs goose-cli.doCheck=true).
- flake.nix: agent = pkgs.goose-cli.overrideAttrs { cargoPatches = [ ... ]; }.

Verified: patch git-applies clean against nixpkgs' goose src; nix build .#agent
compiles + passes the tests; goose --version still 1.28.0. Remove when an upstream-
fixed goose is pinned (the OpenAI Responses side is already fixed in aaif-goose/goose#10344;
the Bedrock side was missed).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(goose): agent-host must use the PATCHED goose (deduplicate the image + apply the fix)

The bedrock patch alone made the agent-host image balloon ~455MB (1110 -> 1565 MiB,
+41%) — and worse, the patch wasn't even taking effect at runtime.

Root cause: the flake's `agent` attr got the patched goose, and the image's gooseLayer
bakes THAT. But services/agent-host/default.nix independently took `goose-cli` via
callPackage and wrapped it onto the agent-host's PATH — that's nixpkgs' UNPATCHED goose,
a different store path. So the image closure shipped goose TWICE (~455MB duplicate), and
the wrapper's PATH ran the unpatched goose, so `goose acp` never got the sanitizer.

Fix: agent-host/default.nix takes `agent ? goose-cli`; the flake passes the patched
`agent`, so the wrapper's PATH goose and the image's gooseLayer are the SAME derivation.

Verified: the agent-host image closure references exactly ONE goose (the patched one)
and is back to 1110 MiB (+0 vs main); the wrapper's PATH points at the patched goose.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
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.

3 participants