{"record":{"id":"913664b09ec1349f","repo":"microsoft/autogen","slug":"tool-choice-specified-but-model-does-not-support-f","errorCode":null,"errorMessage":"tool_choice specified but model does not support function calling","messagePattern":"tool_choice specified but model does not support function calling","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/packages/autogen-ext/src/autogen_ext/models/llama_cpp/_llama_cpp_completion_client.py","lineNumber":421,"sourceCode":"        )\n        return create_result\n\n    async def create_stream(\n        self,\n        messages: Sequence[LLMMessage],\n        *,\n        tools: Sequence[Tool | ToolSchema] = [],\n        tool_choice: Tool | Literal[\"auto\", \"required\", \"none\"] = \"auto\",\n        # None means do not override the default\n        # A value means to override the client default - often specified in the constructor\n        json_output: Optional[bool | type[BaseModel]] = None,\n        extra_create_args: Mapping[str, Any] = {},\n        cancellation_token: Optional[CancellationToken] = None,\n    ) -> AsyncGenerator[Union[str, CreateResult], None]:\n        # Validate tool_choice parameter even though streaming is not implemented\n        if tool_choice != \"auto\" and tool_choice != \"none\":\n            if not self.model_info[\"function_calling\"]:\n                raise ValueError(\"tool_choice specified but model does not support function calling\")\n            if len(tools) == 0:\n                raise ValueError(\"tool_choice specified but no tools provided\")\n            logger.warning(\"tool_choice parameter specified but may not be supported by llama-cpp-python\")\n\n        raise NotImplementedError(\"Stream not yet implemented for LlamaCppChatCompletionClient\")\n        yield \"\"\n\n    # Implement abstract methods\n    def actual_usage(self) -> RequestUsage:\n        return RequestUsage(\n            prompt_tokens=self._total_usage.get(\"prompt_tokens\", 0),\n            completion_tokens=self._total_usage.get(\"completion_tokens\", 0),\n        )\n\n    @property\n    def capabilities(self) -> ModelInfo:\n        return self.model_info\n","sourceCodeStart":403,"sourceCodeEnd":439,"githubUrl":"https://github.com/microsoft/autogen/blob/027ecf0a379bcc1d09956d46d12d44a3ad9cee14/python/packages/autogen-ext/src/autogen_ext/models/llama_cpp/_llama_cpp_completion_client.py#L403-L439","documentation":"create_stream() validates tool_choice before anything else (streaming itself is not implemented). If tool_choice is anything other than 'auto' or 'none' (i.e. 'required', a Tool, or a required-mode value) and the model_info says function_calling is False, this ValueError is raised. The check exists so misconfigured streaming calls fail fast instead of silently misbehaving.","triggerScenarios":"Calling create_stream(messages, tools=..., tool_choice='required') on a client whose model_info (default DEFAULT_MODEL_INFO or user-supplied) has function_calling: False; passing tool_choice=some_tool with a non-tool-calling model.","commonSituations":"Using a shared call site that switches between create() and create_stream(); copy-pasting tool-calling parameters from a GPT-4 config into a small local llama.cpp model; forgetting to set function_calling: True in a custom model_info dict.","solutions":["Set tool_choice='auto' or 'none' when the model does not support function calling","If the model genuinely supports tools, pass model_info with 'function_calling': True to the constructor (DEFAULT_MODEL_INFO has it False)","Note streaming is unimplemented anyway — use create() instead of create_stream()"],"exampleFix":"# before\nclient = LlamaCppChatCompletionClient(model_path=\"m.gguf\")\nasync for chunk in client.create_stream(msgs, tool_choice=\"required\"): ...\n\n# after\nclient = LlamaCppChatCompletionClient(model_path=\"m.gguf\", model_info={\"function_calling\": True, ...})\nresult = await client.create(msgs, tool_choice=\"required\")","handlingStrategy":"validation","validationCode":"choice = \"required\" if (tools and client.capabilities[\"function_calling\"]) else \"auto\"\n# note: create_stream raises NotImplementedError regardless; use create()\nresult = await client.create(messages, tools=tools, tool_choice=choice)","typeGuard":"def supports_forced_tools(client: LlamaCppChatCompletionClient) -> bool:\n    return bool(client.capabilities.get(\"function_calling\"))","tryCatchPattern":"try:\n    ...  # call site with tool_choice\nexcept ValueError as e:\n    if \"does not support function calling\" in str(e):\n        result = await client.create(messages, tool_choice=\"auto\")\n    else:\n        raise","preventionTips":["Set function_calling accurately in model_info at construction","Branch tool_choice on client.capabilities['function_calling'] in shared call sites","Prefer create() over create_stream() for this client"],"tags":["llama-cpp","tool-calling","streaming","model-info"],"backgroundTag":null,"analyzedSha":"027ecf0a379bcc1d09956d46d12d44a3ad9cee14","analyzedAt":"2026-08-15T03:38:00.719Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}