Skip to content

feat(tools): enable strict mode for specific tools#2036

Open
kermanx wants to merge 3 commits into
MoonshotAI:mainfrom
kermanx:kermanx/tool-strict
Open

feat(tools): enable strict mode for specific tools#2036
kermanx wants to merge 3 commits into
MoonshotAI:mainfrom
kermanx:kermanx/tool-strict

Conversation

@kermanx

@kermanx kermanx commented Apr 23, 2026

Copy link
Copy Markdown
Collaborator

Related Issue

N/A

Description

Enable OpenAI/Anthropic strict schema validation for a subset of core tools to improve reliability:

  • Shell (Bash/PowerShell)
  • ReadFile
  • Grep
  • WriteFile
  • StrReplaceFile
  • SetTodoList

Changes:

  1. Added strict: bool = False to the Tool base model (kosong).
  2. Updated CallableTool2 to read the strict class attribute and pass it to Tool.
  3. Updated OpenAI Responses, OpenAI Legacy, and Anthropic tool converters to emit tool.strict.
  4. Added strict: bool = True to each of the 6 tool classes above.

Other tools remain strict=False by default.

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked the related issue, if any.
  • I have added tests that prove my fix is effective or that my feature works.
  • I have run `make gen-changelog` to update the changelog.
  • I have run `make gen-docs` to update the user documentation.

Open in Devin Review

Copilot AI review requested due to automatic review settings April 23, 2026 12:12

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c2c0f02eb6

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

parameters=deref_json_schema(
self.params.model_json_schema(schema_generator=_GenerateJsonSchemaNoTitles)
),
strict=strict,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Normalize schema before setting strict tool mode

This now passes strict=True for several CallableTool2 subclasses without converting the generated Pydantic schema into OpenAI strict-compatible form. model_json_schema() leaves optional/defaulted fields and omits additionalProperties: false, but strict tool mode requires a tighter schema shape; as a result, requests that include these tools can fail with API-side schema validation errors before any tool call runs. Please normalize the schema for strict tools (or gate strict until the schema is transformed) before sending strict.

Useful? React with 👍 / 👎.

devin-ai-integration[bot]

This comment was marked as resolved.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a strict flag on Kosong tool definitions and propagates it through multiple chat-provider adapters, then enables strict schema validation for a small set of core built-in tools in kimi_cli to reduce invalid tool calls.

Changes:

  • Add strict: bool = False to kosong.tooling.Tool and plumb it from CallableTool2 into provider tool payloads (OpenAI Chat Completions, OpenAI Responses, Anthropic).
  • Enable strict = True for core built-in tools: Shell, ReadFile, Grep, WriteFile, StrReplaceFile, SetTodoList.
  • Update changelogs/release notes to document the change.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/kimi_cli/tools/todo/init.py Enable strict mode for SetTodoList.
src/kimi_cli/tools/shell/init.py Enable strict mode for Shell.
src/kimi_cli/tools/file/write.py Enable strict mode for WriteFile.
src/kimi_cli/tools/file/replace.py Enable strict mode for StrReplaceFile.
src/kimi_cli/tools/file/read.py Enable strict mode for ReadFile.
src/kimi_cli/tools/file/grep_local.py Enable strict mode for Grep.
packages/kosong/src/kosong/tooling/init.py Add Tool.strict and propagate CallableTool2.strict into the base Tool definition.
packages/kosong/src/kosong/contrib/chat_provider/openai_responses.py Emit tool.strict in OpenAI Responses tool conversion.
packages/kosong/src/kosong/contrib/chat_provider/anthropic.py Emit tool.strict in Anthropic tool conversion.
packages/kosong/src/kosong/chat_provider/openai_common.py Emit tool.strict in OpenAI Chat Completions tool conversion helper.
packages/kosong/CHANGELOG.md Document new strict field propagation in Kosong.
docs/zh/release-notes/changelog.md Document strict tool validation and Tool/CallableTool2 strict in release notes (ZH).
docs/en/release-notes/changelog.md Document strict tool validation and Tool/CallableTool2 strict in release notes (EN).
CHANGELOG.md Document strict tool validation and Tool/CallableTool2 strict at repo level.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 282 to 293
raise ValueError("Tool params must be a subclass of pydantic.BaseModel")

strict = getattr(cls, "strict", False)
if not isinstance(strict, bool): # type: ignore[reportUnnecessaryIsInstance]
strict = False

self._base = Tool(
name=self.name,
description=self.description,
parameters=deref_json_schema(
self.params.model_json_schema(schema_generator=_GenerateJsonSchemaNoTitles)
),
Comment on lines 152 to 163
def tool_to_openai(tool: Tool) -> ChatCompletionToolParam:
"""Convert a single tool to OpenAI tool format."""
# simply `model_dump` because the `Tool` type is OpenAI-compatible
return {
"type": "function",
"function": {
"name": tool.name,
"description": tool.description,
"parameters": tool.parameters,
"strict": tool.strict,
},
}
Comment on lines 625 to 631
def _convert_tool(tool: Tool) -> ToolParam:
return {
"name": tool.name,
"description": tool.description,
"input_schema": tool.parameters,
"strict": tool.strict,
}
@kermanx
kermanx force-pushed the kermanx/tool-strict branch 2 times, most recently from b75f00b to a4124b6 Compare April 23, 2026 12:26
@kermanx
kermanx force-pushed the kermanx/tool-strict branch from a4124b6 to b12cc23 Compare April 23, 2026 12:29
chatgpt-codex-connector[bot]

This comment was marked as resolved.

OpenAI strict mode requires additionalProperties: false and all properties
in required. Pydantic does not generate these by default.

Previously, a generic make_openai_strict_schema was added to kosong's
tooling layer. This is wrong because Anthropic's API validator rejects
additionalProperties: false in tool schemas.

Move the transform into the OpenAI-specific adapters
(openai_common.py and openai_responses.py) using the official
openai.lib._pydantic._ensure_strict_json_schema. Kimi and openai_legacy
adapters automatically benefit since they reuse tool_to_openai().
@kermanx

kermanx commented Apr 23, 2026

Copy link
Copy Markdown
Collaborator Author

@codex

chatgpt-codex-connector[bot]

This comment was marked as resolved.

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.

2 participants