vllm/tool_parsers
Every --tool-call-parser name resolves here. ParserManager.get_parser
composes the tool parser chosen by name with the reasoning parser into the
unified Parser the serving layer uses. The ToolParser interface itself is
legacy: it is kept so existing in-tree parsers and out-of-tree plugins keep
working, not as the base for new ones.
Layout
abstract_tool_parser.py—ToolParser(extract_tool_calls,extract_tool_calls_streaming,adjust_request) andToolParserManager.__init__.py—_TOOL_PARSERS_TO_REGISTER, the name → (file, class) table that lazily registers every built-in parser.structural_tag_registry.py— structural-tag builders used to constrain tool-call output fortool_choice="required"/ named tools.<model>_tool_parser.py— one file per family. Either a subclass of aParserToolAdaptergenerated from avllm/parser/<model>.pyengine grammar (mistral_tool_parser.py,kimi_k2_tool_parser.py; the_engine_suffix is not applied consistently), or a self-containedToolParsersubclass.
Guidelines
- Do not change the
ToolParserinterface inabstract_tool_parser.py. Out-of-tree plugins loaded throughToolParserManager.import_tool_parsersubclass it. New capabilities go onParserinvllm/parser/; if a legacy parser needs the same capability,DelegatingParsersupplies the default. - For a new model, implement a unified
Parserinvllm/parser/first, then expose it here as a thin adapter subclass plus an entry in_TOOL_PARSERS_TO_REGISTER. - The
_TOOL_PARSERS_TO_REGISTERkey is what users pass on the command line; treat renames as breaking. - Keep adapters thin: registration,
adjust_requesttweaks, and class attributes. Parsing logic belongs invllm/parser/. - Keep a model-specific fix inside that model's
<model>_tool_parser.py, or its grammar invllm/parser/<model>.py, where possible. Touchabstract_tool_parser.pyorstructural_tag_registry.pyonly for behavior every parser needs, and say so in the PR. - Set
structural_tag_modelonly to a key inSUPPORTED_STRUCTURAL_TAG_MODELS(an xgrammar builtin, or one registered withregister_vllm_structural_tag). It only takes effect underVLLM_ENFORCE_STRICT_TOOL_CALLING, where it also disables the generic required/named handling for that parser. - Comment only where the code alone would leave a reader with a question —
a request tweak in
adjust_request, a marker handled unusually, a model quirk being worked around. Keep it minimal and concise.