How I Fixed DeepSeek's Tool Call Failures in 30 Lines
How I Fixed DeepSeek's Tool Call Failures in 30 Lines "How I Fixed DeepSeek's Tool Call Failures in 30 Lines" Posted by: [Your name] The Problem Running Hermes with DeepSeek V4 Pro/Flash. Tool calls fail 50+ times in a row. Same error looped. Context window fills with garbage. Session dies. Sound familiar? It's not the model. It's the harness. What Actually Happens DeepSeek (and GLM, Qwen, etc.) makes the same 4 mistakes on tool calls: Table Mistake Example What Schema Wants null for optional {"file": null} omit the key entirely JSON string as array {"items": '["a","b"]'} {"items": ["a","b"]} Empty {} placeholder {"args": {}} {"args": []} Bare string for array {"name": "foo"} {"name": ["foo"]} Your validator (Zod, Pydantic) rejects it. Error goes back to model. Model sends same bad call again. 56 times average. Then it gives up or hallucinates. The Fix: Repair Harness Don't send the error back. Fix it deterministically, run it, and teach the model what it should have done. This is 4 small repair functions. ~30 lines each. Ordered carefully. Python # repairs/plugin.py โ Drop this into your agent import json from dataclasses import dataclass from typing import Dict, Any, List, Optional @dataclass class RepairResult: changed: bool tool_call: Dict[str, Any] repair_id: str description: str before: Optional[str] after: Optional[str] class ToolRepairHarness: def __init__(self): self.repair_stats = {} def repair(self, tool_call: Dict[str, Any], schema: Dict[str, Any]): fixed = json.loads(json.dumps(tool_call)) # deep copy applied = [] # REPAIR 001: null โ omit (optional fields) before = json.dumps(fixed.get("arguments", {})) args = dict(fixed.get("arguments", {})) required = schema.get("required", []) for key, value in list(args.items()): if value is None and key not in required: del args[key] if json.dumps(args) != before: fixed["arguments"] = args applied.append(RepairResult(True, fixed, "001",