Hey,
I've been trying to write an AI agent for OpenAI's GPT-5, but using the @Generable Tool
types from the FoundationModels
framework, which is super awesome btw!
I'm having trouble implementing the tool calling, though. When I receive a tool call from the OpenAI api, I do the following:
- Find the tool in my
[any Tool]
array via the tool name I get from the model
if let tool = tools.first(where: { $0.name == functionCall.name }) {
// ...
}
- Parse the arguments of the tool call via
GeneratedContent(json:)
let generatedContent = try GeneratedContent(json: functionCall.arguments)
- Pass the tool and arguments to a function that calls
tool.call(arguments: arguments)
and returns the tool's output type
private func execute<T: Tool>(_ tool: T, with generatedContent: GeneratedContent) async throws -> T.Output {
let arguments = try T.Arguments.init(generatedContent)
return try await tool.call(arguments: arguments)
}
Up to this point, everything is working as expected. However, the tool's output type is any PromptRepresentable
and I have no idea how to turn that into something that I can encode and send back to the model. I assumed there might be a way to turn it into a GeneratedContent
but there is no fitting initializer.
Am I missing something or is this not supported? Without a way to return the output to an external provider, it wouldn't really be possible to use FoundationModels Tool type I think. That would be unfortunate because it's implemented so elegantly.
Thanks!
You could make your tool definition return a concrete type, e.g. String
, or GeneratedContent
. Then, add a generic constraint to your execute
method on the T
type.
private func execute<T: Tool>(_ tool: T, with generatedContent: GeneratedContent) async throws -> GeneratedContent where T.Output == GeneratedContent