Repository navigation
fix(koog): never put a tool call without ID or name into history - #1190
Conversation
Copilot rejects the whole request with HTTP 400 "tool call must have a tool call ID and function name" when any call in the resent history lacks an ID or name. assemble() copied both straight from the stream frame, so one malformed call poisoned every later request. Blank IDs now get a generated one, blank names become unknown_tool, and the tool result uses the same ID as the call.
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
|
IDE Compatibility Matrix
Generated from the real-IDE integration bench (
Logged IDE errors (non-gating)Scraped from the IDE log during the run. These do not fail a matrix cell (the cell reflects the tool's MCP response) — they are listed for visibility while the bench matures.
|
There was a problem hiding this comment.
🟢 Approval recommended
The normalization is narrow and preserves call/result pairing; additional regression coverage is a nonblocking improvement.
1 open issue
What changed in this PR
Hardens Koog conversation history against malformed tool-call metadata that can cause Copilot HTTP 400 responses.
Changes:
- Generates IDs for null or blank call IDs and substitutes
unknown_toolfor blank names. - Uses the execution ID consistently in tool results.
| File | Description |
|---|---|
| plugin-core/src/main/java/com/github/catatafishen/agentbridge/client/koog/KoogConversation.kt | Normalizes streamed tool-call metadata and aligns result IDs. |
Review effort: Balanced
| id = frame.id?.takeIf { it.isNotBlank() } ?: ("koog-" + UUID.randomUUID()), | ||
| tool = frame.name.ifBlank { "unknown_tool" }, |




Copilot returns HTTP 400
tool call must have a tool call ID and function namewhen any tool call in the resent history lacks an ID or name.KoogConversation.assemble()copied both straight from the stream frame, so a single malformed call mid-run poisoned every later request in the conversation.koog-<uuid>; blank names becomeunknown_tool.executeCallnow uses the same fallback ID for the tool result as for the call.Not reproduced locally; this hardens the history against the suspected cause. If it recurs, the provider's raw frame should be logged.