Skip to content

Accept images in decisions - #338

Open
anbuzin wants to merge 4 commits into
rename-decisionsfrom
implement-multimodal-decisions
Open

anbuzin wants to merge 4 commits into
rename-decisionsfrom
implement-multimodal-decisions

Conversation

@anbuzin

@anbuzin anbuzin commented Nov 2, 2026 •

Copy link
Copy Markdown
Collaborator

Decision models are now multimodal, and so we're adding support for that.

state = {"photo": ai.file_part(data), "note": "Delivered today."}

We can no longer use pydantic.JsonValue for typing, so we're replacing it with roughly the same thing plus FilePart.

Accept `FilePart`s anywhere in decision state and in question
`instructions` and `criteria`, alongside text and JSON, e.g.
`{"photo": ai.file_part(data), "note": "..."}`. `DecisionInput` is now
text, a file, or JSON with files at any depth. It validates like
`pydantic.JsonValue`: an invalid value gives one error at its path. A
plain `str` is always text, and a dict shaped like a file stays JSON.

The TypeSafe protocol turns each file part into an SDK `Image`, which
the SDK sends as an asset with a reference in its place, and sends the
image opt-in header. URLs are downloaded, a repeated file part is sent
once, and files that are not images are rejected. AI Gateway v4 has no
wire format for files in decision requests yet, so it rejects them
before it sends the request.
The TypeSafe example puts images inside structured state and in a score
criterion. The OpenAI example puts them where the OpenAI Decisions API
accepts them: in a list of text and file parts as state, and in one
question's instructions.

The OpenAI example raises `NotImplementedError` until the OpenAI
decisions protocol lands. TypeSafe is not on models.dev yet, so its
example builds the model with `TypeSafeProvider()`.
@vercel

vercel Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
ai-python Ready Ready Preview, v0 Nov 2, 2026 10:30pm UTC

@socket-security

socket-security Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatedpypi/​typesafe-sdk@​0.7.2 ⏵ 0.7.5100 +1100100100100

View full report

Statically type DecisionInput with covariant Sequence and Mapping so a
typed list or dict such as list[str | int] is accepted without a cast.
Validation still stores every sequence as a list and every mapping as a
dict, so providers keep walking plain JSON shapes. Binary data is still
rejected rather than read as a list of ints.
Comment on lines +127 to +133
type DecisionInput = Annotated[
Annotated[str, pydantic.Tag("str")]
| Annotated[messages.FilePart, pydantic.Tag("FilePart")]
| Annotated[dict[str, _DecisionValue], _AS_DICT, pydantic.Tag("dict")]
| Annotated[list[_DecisionValue], _AS_LIST, pydantic.Tag("list")],
_INPUT_DISCRIMINATOR,
]

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Hmmmm: will serializing something with a FilePart and then deserializing it back have any way to preserve the file part? Probably not, right?

But I guess that's kind of inevitable without more of a schema for it...

@msullivan msullivan left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I'm still a little unsure about the image embedding situation but don't have a better plan yet

This branch was successfully deployed

1 active deployment
Preview — 2f6dbb66 Deployed Nov 2, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants