Skip to content

fix(core): resolve JSON Pointer array indexes in $ref paths - #4719

Open
hsusul wants to merge 2 commits into
openai:mainfrom
hsusul:fix/strict-schema-json-pointer-array-index
Open

fix(core): resolve JSON Pointer array indexes in $ref paths#4719
hsusul wants to merge 2 commits into
openai:mainfrom
hsusul:fix/strict-schema-json-pointer-array-index

Conversation

@hsusul

@hsusul hsusul commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Summary

`resolve_ref()` treated every JSON Pointer hop as a dict lookup. A valid pointer such as `#/allOf/0` therefore crashed with `AssertionError: encountered non-dictionary entry` because `allOf` is an array.

JSON Pointer (RFC 6901) uses decimal array indexes. OpenAPI and MCP schemas commonly `$ref` into `allOf` / `anyOf` / `prefixItems` members. Default `FunctionTool` construction (`strict_json_schema=True`) and MCP `convert_schemas_to_strict=True` run this path, so those tools fail at setup.

Reproduction

from agents.tool import FunctionTool

schema = {
    \"type\": \"object\",
    \"properties\": {
        \"value\": {\"\$ref\": \"#/allOf/0\", \"description\": \"first member\"},
    },
    \"allOf\": [
        {\"type\": \"object\", \"properties\": {\"a\": {\"type\": \"string\"}}, \"required\": [\"a\"], \"additionalProperties\": False},
        {\"type\": \"object\", \"properties\": {\"b\": {\"type\": \"integer\"}}, \"required\": [\"b\"], \"additionalProperties\": False},
    ],
}

FunctionTool(name=\"t\", description=\"d\", params_json_schema=schema, on_invoke_tool=lambda ctx, s: s)
# Before: AssertionError
# After: schema is inlined as a strict object

Solution

Walk dict keys and RFC 6901 array indexes. Reject non-integer tokens, leading zeros, and out-of-range indexes with `ValueError`. Nested `$id` resource checks still apply only to dict nodes.

Test plan

  • Direct `resolve_ref("#/allOf/0")` and `#/allOf/1`
  • Invalid array token raises `ValueError`
  • `ensure_strict_json_schema` inlines a sibling `$ref` into an `allOf` member
  • `uv run pytest tests/test_strict_schema.py` (75 passed)
  • `ruff` / `pyright` on the changed files

Issue number

N/A

Checks

  • I've added new tests, if relevant
  • I've run format, lint, typecheck, and targeted tests
  • If using Codex, I've run `/review` before submitting this PR

resolve_ref treated every pointer hop as a dict lookup, so refs such as
#/allOf/0 crashed with AssertionError. Walk RFC 6901 array indexes so
OpenAPI/MCP composed schemas can be converted to strict form.

@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: 8da27ea86b

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/agents/strict_schema.py Outdated
@seratch seratch changed the title fix(strict_schema): resolve JSON Pointer array indexes in $ref paths fix(core): resolve JSON Pointer array indexes in $ref paths Aug 27, 2026

@seratch seratch left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The array-index support is needed, but str.isdigit() accepts non-ASCII numerals such as Arabic-Indic and full-width digits. Those are not valid JSON Pointer array-index tokens and can cause a malformed third-party schema to resolve to a different array member instead of being rejected.

Please restrict the token to the ASCII array-index grammar, preserving the existing leading-zero and bounds checks, and add cases for Arabic-Indic, full-width, and mixed digit strings.

RFC 6901 array-index tokens must use JSON decimal digits. Restrict
validation to ASCII 0-9 instead of str.isdigit(), which also accepts
Arabic-Indic and full-width numerals that int() would parse to a
different member than intended.
@hsusul

hsusul commented Aug 27, 2026

Copy link
Copy Markdown
Contributor Author

Addressed in 6b4ee86.

_json_pointer_child now validates array-index tokens with ASCII 0-9 only, instead of str.isdigit(). Leading-zero and out-of-range checks are unchanged.

Added regression coverage for Arabic-Indic (\u0660, \u0661), full-width (\uff10, \uff11), and mixed ASCII/non-ASCII digit strings.

@seratch seratch added this to the 0.22.x milestone Aug 27, 2026

@seratch seratch left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks, the resolver now follows RFC 6901's ASCII array-index grammar, and I do not see a remaining defect in the implementation itself. Before merge, please strengthen the regression coverage at the supported boundary.

The current test_ensure_strict_json_schema_inlines_ref_to_allof_member fixture is unsatisfiable: the root permits only value, while the two allOf branches respectively require and permit only a or b. It therefore proves traversal, but not that a usable strict schema is produced. Please replace it with a satisfiable valid JSON Schema and exercise FunctionTool construction or an equivalent public conversion boundary. Also add leading-zero and out-of-range cases, since regressions in those branches could accept or select the wrong array location.

With those focused tests and green CI, this should be ready.

@seratch seratch removed this from the 0.22.x milestone Aug 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants