Overview
enum JSONValue: Sendable, Equatable, Codable
Tool input and output can be any JSON, so the SDK uses JSONValue instead of Any. That means you can read it without casting, and pass it between threads safely.
Reading Values
Looking up a key
nil if the key is missing or the value is not an object, so you can chain safely:
Getting a Swift type
nil if the value is a different type:
numberValue is the forgiving one. It works for whole numbers and decimals alike, so both 9 and 9.0 read cleanly. intValue is stricter and returns nil for 9.0. If a value might arrive either way, read it with numberValue.Handling every case
To cover all the possibilities, switch on the value:Writing Values
Build results from the cases:Reporting a failure
An object with anerror key is how you report a problem anywhere in the SDK. The agent sees the tool as failed, and ConversationState shows the card as failed too:
Using Your Own Types
JSONValue works with Codable, so you can convert to and from your own types with JSONEncoder and JSONDecoder.
Reading input into a struct
Returning a struct
How Values Are Read
The SDK tries the cases in this order: null,Bool, Int, Double, String, object, array. Two things follow from that:
- A whole number is always read as
.int, never.number. If the agent might send either, read it withnumberValue. - Anything that matches none of the cases is read as
.nullinstead of failing, so an odd tool result will not break the reply.
Size Limit
Tool results can be at most 20 KB of JSON. Anything larger fails with400 VALIDATION_INVALID_BODY.
Related
Client-Side Tools
Where you use JSONValue most
Streaming Types
ToolCallInfo and ToolResultInfo
ChatResponse
Message parts
SwiftUI
Showing tool input and output
