# NousResearch/hermes-agent · Tool schema required field handling for strict OpenAI backends

## Open now

- 1 issue, 3 PRs open on GitHub.
- #60752: \[Bug\]: "Tool schema with required: null causes HTTP 400 on strict OpenAI-compatible backends (e.g. arityflow.top) since v0.11+"
- PR #59926: fix(delegate): add default=\[\] to tasks schema for strict OpenAI backends (#59386)
- PR #60766: fix: strip required:null from tool schemas for strict OpenAI-compatible backends
- PR #61204: fix(tools): strip required: null from tool schemas to prevent HTTP 400

These issues and fixes concern how the \`required\` field in tool/JSON schemas is handled when communicating with strict OpenAI-compatible backends, specifically whether it should be preserved as an empty array, injected when missing, or stripped when null/malformed to avoid HTTP 400 errors. The cluster centers on Moonshot/Kimi and delegate_task schemas, with overlapping but sometimes conflicting approaches to the fix.

## TL;DR

- 21 member(s): 1 open issue(s), 3 closed issue(s), 3 open PR(s), 3 merged PR(s), 11 PR(s) closed without merging.
- A fix was merged to main in PR #68154. Verify it addresses your case.
- **Recommended:** read PR #68154 (and any competing PRs below) before filing. Confirm the merged change covers your symptom.

## Maintainer resolution verdict

- Internal-tracker verdict over this cluster's issue members: `partially_resolved` · deciding PR(s): `pr-68154,pr-112169,pr-115854`. This is distinct from the fix status above. Weigh it yourself.

## How this cluster was grouped

- Link evidence (`STRUCTURAL_PARTIAL`): some members are connected by structural evidence (shared changed files, or a closing/superseded reference); the rest are joined by an automated relevance judgement over their text.
- Members outside that structural core may belong to a different underlying problem.
- Pairwise link density `0.09`: the share of member pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36. `1.00` means every pair is linked.

## Open related issues

- #60752: \[Bug\]: "Tool schema with required: null causes HTTP 400 on strict OpenAI-compatible backends (e.g. arityflow.top) since v0.11+"

## Closed / duplicate issues

- #56123: fix: schema_sanitizer strips required field causing HTTP 400 on strict OpenAI-compatible backends
- #59386: \[Bug\]: \`delegate_task\` schema causes HTTP 400 / non-retryable crash on strict OpenAI-compatible backends
- #66835: Moonshot/Kimi: tool schemas with empty properties missing "required" array cause HTTP 400

## Prior & competing PRs

- **#56136: fix(tools): preserve empty required array instead of dropping key**. closed without merge · fix tier `suggested`
  - maintainer direction: category `superseded_by_pr`; implication `superseded`; refs `#20151`, `#20151`
  - _suggested-tier fix detail withheld; re-request with `?tier=all` to include it._
- **#68154: fix(moonshot): inject required:\[\] on object schemas to fix kimi HTTP 400 (#66835)**. merged to main · fix tier `verified`
  - maintainer direction: category `merged`; implication `superseded`
  - files: `agent/moonshot_schema.py`, `tests/agent/test_moonshot_schema.py`, `tests/agent/transports/test_chat_completions.py`
- **#112169: fix(tools): zero-argument tool schemas keep \`required: \[\]\` so strict OpenAI-compatible proxies stop 400ing (#111684, #59386, salvage #20151)**. merged to main · fix tier `verified`
  - maintainer direction: category `merged`; implication `superseded`
  - files: `contributors/emails/[redacted:email]`, `tests/tools/test_schema_sanitizer.py`, `tools/schema_sanitizer.py`
- **#115854: fix(mcp): MCP tool schemas keep required: \[\] so strict OpenAI-compatible backends stop rejecting requests (#56123, salvage #106288)**. merged to main · fix tier `verified`
  - maintainer direction: category `merged`; implication `superseded`
  - files: `contributors/emails/[redacted:email]`, `tests/tools/test_mcp_tool.py`, `tests/tools/test_schema_sanitizer.py`, `tools/mcp_tool_schema.py`, `tools/schema_sanitizer.py`
- **#59416: fix: drop malformed required schema values**. closed without merge
  - maintainer direction: category `superseded_by_pr`; implication `superseded`; refs `bd0affe5e5f723579df8902852f5d0c47795f355`
- **#59459: fix: keep empty required: \[\] instead of removing key (#59386)**. closed without merge
  - maintainer direction: category `merged_via`; implication `superseded`; refs `40b47b84e7`, `#112169`
- **#59684: fix(delegate_task): mark tasks parameter nullable for strict OpenAI-compatible backends**. closed without merge
  - maintainer direction: category `stale_abandoned`; implication `active`
- **#59926: fix(delegate): add default=\[\] to tasks schema for strict OpenAI backends (#59386)**. open
  - maintainer direction: category `uncategorized`; implication `needs_llm`
  - files: `tools/delegate_tool.py`
- **#60702: fix(schema): preserve empty required array in sanitizer and add additionalProperties to delegate_task (#59386)**. closed without merge
  - maintainer direction: category `stale_abandoned`; implication `active`
- **#60755: fix(schema): drop null required from tool schemas**. closed without merge
  - maintainer direction: category `duplicate_of`; implication `duplicate`; refs `#59416`, `#59416`, `#29329`, `#59421`, `#60752`
- **#60766: fix: strip required:null from tool schemas for strict OpenAI-compatible backends**. open
  - maintainer direction: category `duplicate_of`; implication `duplicate`; refs `#29329`, `#60755`, `#59416`
  - files: `tools/mcp_tool.py`, `tools/schema_sanitizer.py`
- **#61204: fix(tools): strip required: null from tool schemas to prevent HTTP 400**. open
  - maintainer direction: category `duplicate_of`; implication `duplicate`; refs `#59416`, `#59416`, `#29329`, `#60766`, `#29329`, `#60702`
  - files: `tests/tools/test_schema_sanitizer.py`, `tools/schema_sanitizer.py`
- **#66849: fix(tools): keep empty required array instead of stripping it**. closed without merge
  - maintainer direction: category `merged_via`; implication `superseded`
- **#66853: fix(moonshot): ensure required array is always present in tool schemas**. closed without merge
  - maintainer direction: category `duplicate_of`; implication `duplicate`; refs `#66852`, `#66852`
- **#66855: fix(agent): inject empty required array on Moonshot object schemas (#66835)**. closed without merge
  - maintainer direction: category `merged_via`; implication `superseded`; refs `#68154`
- **#67430: fix(moonshot): inject required: \[\] on object schemas missing it**. closed without merge
  - maintainer direction: category `superseded_by_pr`; implication `superseded`; refs `#68154`, `#66855`, `#66852`
- **#71220: fix(tools): keep empty required\[\] instead of dropping the key (#59386)**. closed without merge
  - maintainer direction: category `duplicate_of`; implication `duplicate`; refs `#59459`, `#59459`

## Fix status

- Merged to main in PR #68154 (cited above). No release data is tracked. Verify downstream.
- Fix last verified (merged) `2026-09-19`.
- Subsystem: `agent`
