docs: clarify format= value contract and model_validate_json pattern#1333
Merged
planetf1 merged 3 commits intoJun 24, 2026
Merged
Conversation
`format=` on act/aact/instruct/ainstruct constrains token generation to
JSON matching the Pydantic schema. The thunk's `.value` is always a str,
not a parsed model instance — callers must parse explicitly:
planet = Planet.model_validate_json(str(result))
The previous act-and-aact.md example only hinted at this in a comment.
This change makes the full pattern visible in working code, adds a
callout noting that `cast(Planet, result.value)` silently type-checks
but fails at runtime, and covers the async and sampling-result variants.
enforce-structured-output.md now mentions act(format=...) alongside
instruct(format=...) in the table and choosing-between sections, and
adds the same cast warning to Pattern 2.
Docstrings for format= in act/aact/instruct/ainstruct (both session.py
and functional.py) and ComputedModelOutputThunk.value (base.py) are
updated to match.
Closes generative-computing#1273. Closes generative-computing#1274.
Assisted-by: Claude Code
Signed-off-by: Nigel Jones <jonesn@uk.ibm.com>
4 tasks
Post-review polish from independent 3-reviewer pass: - Replace RST double-backtick literals (``x``) with plain single-backtick inline code (`x`) in all eight format= docstrings (functional.py, session.py) and the ComputedModelOutputThunk.value docstring — AGENTS.md §5 prohibits RST markup inside docstrings - In base.py, replace `self.value` example with `str(result)` to match the pattern used consistently across all user-facing docs - Drop redundant "If set," prefix from format= docstrings — the optional nature is already declared in the signature; "Constrains generation to..." is cleaner - enforce-structured-output.md: tighten "same contract" to "same JSON-string contract" so the cross-reference is self-explanatory No functional changes; documentation/docstring only. Assisted-by: Claude Code Signed-off-by: Nigel Jones <jonesn@uk.ibm.com>
…in table The intro table was mixing two concerns — when to choose a pattern and what each pattern returns. Split them: - Strip both rows to pure selection criteria - Add a prose sentence below the table stating the contract difference: @Generative returns the Pydantic instance directly; instruct/act(format=...) return a thunk whose .value is a JSON string to parse with model_validate_json Assisted-by: Claude Code Signed-off-by: Nigel Jones <jonesn@uk.ibm.com>
planetf1
marked this pull request as ready for review
June 24, 2026 09:49
planetf1
enabled auto-merge
June 24, 2026 10:00
jakelorocco
approved these changes
Jun 24, 2026
Merged
via the queue into
generative-computing:main
with commit Jun 24, 2026
70d9f5f
9 checks passed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1273. Closes #1274.
Supersedes #1284, which attempted a code-level fix. The maintainer decision
is to document the behaviour clearly instead.
What this PR does
format=onact/aact/instruct/ainstructconstrains the backend'stoken generation to JSON matching the declared Pydantic schema. The thunk's
.valueis always astr— not a parsed model instance. The previous docsonly hinted at this in a terse comment; callers had to guess the parse step
and could silently introduce a cast footgun.
docs/how-to/act-and-aact.md(schema definition →
act()call →model_validate_jsonparse)explicitly (
cast(Planet, result.value)passes type checking but raisesAttributeErrorat runtime), and covering thereturn_sampling_resultsunwrap variant
aact()section confirming the samecontract applies there
docs/how-to/enforce-structured-output.mdinstruct(format=...)andact(format=...)into a single tablerow (they share the same contract)
return_sampling_resultsunwrap note
act(format=...)directlyDocstrings (
mellea/core/base.py,mellea/stdlib/session.py,mellea/stdlib/functional.py)ComputedModelOutputThunk.value— expanded from "Gets the value of theblock" to describe the JSON-string contract and the parse step
formatparameter — updated inact,aact,instruct,ainstruct(both
session.pyandfunctional.py) from "BaseModel for constraineddecoding" to include the
.value-is-str contract and themodel_validate_jsonpatternWhy not a code fix?
A code fix (#1284) was explored and declined in review. The design intent is
that
format=is a generation hint, not a typing signal: a componentdeclares the shape of its output (e.g. a
Messagecomponent returns aMessage), andformat=is a separate concern. The clean code-level pathis
@generative, which returns a typed instance directly. The docs now saythis clearly.
The type-narrowing gap (#1274) remains open as a future improvement,
tracked in #1313.