Skip to content

infer: emit $ref/$defs for recursive types instead of erroring - #79

Open
rafaeljusto wants to merge 1 commit into
google:mainfrom
rafaeljusto:recursive-types
Open

rafaeljusto wants to merge 1 commit into
google:mainfrom
rafaeljusto:recursive-types

Conversation

@rafaeljusto

Copy link
Copy Markdown
Contributor

For and ForType previously returned "cycle detected for type ..." when a Go type referred to itself, directly or indirectly. This made it impossible to generate a schema for self-referential types such as jsonschema.Schema itself, which is a common need when accepting a JSON schema as input to an MCP tool.

Now, when a named type closes a cycle, its schema is emitted once under "$defs" and referenced with "$ref" wherever it recurs. The recursion bookkeeping (seen set, assigned def names, collected defs) is threaded through forType via a shared inferState. Output for non-recursive types is unchanged: no "$defs" is added and no "$ref" is emitted.

Verified end to end against the modelcontextprotocol/go-sdk, which depends on this library: ForType, Resolve{ValidateDefaults:true}, Validate, ApplyDefaults, the JSON wire round-trip, and AddTool all handle the generated recursive schemas, and the SDK's own test suite passes.

Resolves #46

@google-cla

google-cla Bot commented Jun 29, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@rafaeljusto

rafaeljusto commented Jun 29, 2026 •

Copy link
Copy Markdown
Contributor Author

❌ a0abba9 Co-Author: <no****y​@anthropic.com>

Oh, looks like I cannot set the co-author thing due to the CLA rules (Claude Opus 4.8 (1M context) <noreply@anthropic.com>).

image

I will force-push again.

For and ForType previously returned "cycle detected for type ..." when a
Go type referred to itself, directly or indirectly. This made it
impossible to generate a schema for self-referential types such as
jsonschema.Schema itself, which is a common need when accepting a JSON
schema as input to an MCP tool.

Now, when a named type closes a cycle, its schema is emitted once under
"$defs" and referenced with "$ref" wherever it recurs. The recursion
bookkeeping (seen set, assigned def names, collected defs) is threaded
through forType via a shared inferState. Output for non-recursive types
is unchanged: no "$defs" is added and no "$ref" is emitted.

Verified end to end against the modelcontextprotocol/go-sdk, which
depends on this library: ForType, Resolve{ValidateDefaults:true},
Validate, ApplyDefaults, the JSON wire round-trip, and AddTool all
handle the generated recursive schemas, and the SDK's own test suite
passes.

Resolves google#46
@karolpiotrowicz

Copy link
Copy Markdown
Contributor

@wolo-lab — routing this to you for a direction call rather than a code review.

For and ForType currently return "cycle detected" for a self-referential Go type. This change emits the type once under $defs and references it with $ref wherever it recurs, so recursive types become expressible.

No exported signature changes, which is why it is easy to miss as a scope call. What changes is the shape of the schema these functions emit, and that is effectively an output contract: anything comparing, storing or serving generated schemas sees different JSON. The author states output for non-recursive types is unchanged and reports verifying end to end against modelcontextprotocol/go-sdk, which depends on this library — and adk-go depends on go-sdk, so the change reaches us transitively. That is the part worth a deliberate decision.

Open 72 days. Happy to run a full review once there is a direction.

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.

Support self-referential structures

3 participants