feat(app-server): add ThreadItem::DynamicToolCall (#12732)

Previously, clients would call `thread/start` with dynamic_tools set,
and when a model invokes a dynamic tool, it would just make the
server->client `item/tool/call` request and wait for the client's
response to complete the tool call. This works, but it doesn't have an
`item/started` or `item/completed` event.

Now we are doing this:
- [new] emit `item/started` with `DynamicToolCall` populated with the
call arguments
- send an `item/tool/call` server request
- [new] once the client responds, emit `item/completed` with
`DynamicToolCall` populated with the response.

Also, with `persistExtendedHistory: true`, dynamic tool calls are now
reconstructable in `thread/read` and `thread/resume` as
`ThreadItem::DynamicToolCall`.
This commit is contained in:
Owen Lin
2026-02-25 12:00:10 -08:00
committed by GitHub
parent 73eaebbd1c
commit a0fd94bde6
37 changed files with 2436 additions and 113 deletions

View File

@@ -1640,50 +1640,6 @@
],
"type": "object"
},
"DynamicToolCallOutputContentItem": {
"oneOf": [
{
"properties": {
"text": {
"type": "string"
},
"type": {
"enum": [
"inputText"
],
"title": "InputTextDynamicToolCallOutputContentItemType",
"type": "string"
}
},
"required": [
"text",
"type"
],
"title": "InputTextDynamicToolCallOutputContentItem",
"type": "object"
},
{
"properties": {
"imageUrl": {
"type": "string"
},
"type": {
"enum": [
"inputImage"
],
"title": "InputImageDynamicToolCallOutputContentItemType",
"type": "string"
}
},
"required": [
"imageUrl",
"type"
],
"title": "InputImageDynamicToolCallOutputContentItem",
"type": "object"
}
]
},
"DynamicToolCallParams": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
@@ -1716,7 +1672,7 @@
"properties": {
"contentItems": {
"items": {
"$ref": "#/definitions/DynamicToolCallOutputContentItem"
"$ref": "#/definitions/v2/DynamicToolCallOutputContentItem"
},
"type": "array"
},
@@ -3008,6 +2964,70 @@
"title": "DynamicToolCallRequestEventMsg",
"type": "object"
},
{
"properties": {
"arguments": {
"description": "Dynamic tool call arguments."
},
"call_id": {
"description": "Identifier for the corresponding DynamicToolCallRequest.",
"type": "string"
},
"content_items": {
"description": "Dynamic tool response content items.",
"items": {
"$ref": "#/definitions/v2/DynamicToolCallOutputContentItem"
},
"type": "array"
},
"duration": {
"allOf": [
{
"$ref": "#/definitions/Duration"
}
],
"description": "The duration of the dynamic tool call."
},
"error": {
"description": "Optional error text when the tool call failed before producing a response.",
"type": [
"string",
"null"
]
},
"success": {
"description": "Whether the tool call succeeded.",
"type": "boolean"
},
"tool": {
"description": "Dynamic tool name.",
"type": "string"
},
"turn_id": {
"description": "Turn ID that this dynamic tool call belongs to.",
"type": "string"
},
"type": {
"enum": [
"dynamic_tool_call_response"
],
"title": "DynamicToolCallResponseEventMsgType",
"type": "string"
}
},
"required": [
"arguments",
"call_id",
"content_items",
"duration",
"success",
"tool",
"turn_id",
"type"
],
"title": "DynamicToolCallResponseEventMsg",
"type": "object"
},
{
"properties": {
"item_id": {
@@ -9094,6 +9114,58 @@
"title": "DeprecationNoticeNotification",
"type": "object"
},
"DynamicToolCallOutputContentItem": {
"oneOf": [
{
"properties": {
"text": {
"type": "string"
},
"type": {
"enum": [
"inputText"
],
"title": "InputTextDynamicToolCallOutputContentItemType",
"type": "string"
}
},
"required": [
"text",
"type"
],
"title": "InputTextDynamicToolCallOutputContentItem",
"type": "object"
},
{
"properties": {
"imageUrl": {
"type": "string"
},
"type": {
"enum": [
"inputImage"
],
"title": "InputImageDynamicToolCallOutputContentItemType",
"type": "string"
}
},
"required": [
"imageUrl",
"type"
],
"title": "InputImageDynamicToolCallOutputContentItem",
"type": "object"
}
]
},
"DynamicToolCallStatus": {
"enum": [
"inProgress",
"completed",
"failed"
],
"type": "string"
},
"DynamicToolSpec": {
"properties": {
"description": {
@@ -12895,6 +12967,59 @@
"title": "McpToolCallThreadItem",
"type": "object"
},
{
"properties": {
"arguments": true,
"contentItems": {
"items": {
"$ref": "#/definitions/v2/DynamicToolCallOutputContentItem"
},
"type": [
"array",
"null"
]
},
"durationMs": {
"description": "The duration of the dynamic tool call in milliseconds.",
"format": "int64",
"type": [
"integer",
"null"
]
},
"id": {
"type": "string"
},
"status": {
"$ref": "#/definitions/v2/DynamicToolCallStatus"
},
"success": {
"type": [
"boolean",
"null"
]
},
"tool": {
"type": "string"
},
"type": {
"enum": [
"dynamicToolCall"
],
"title": "DynamicToolCallThreadItemType",
"type": "string"
}
},
"required": [
"arguments",
"id",
"status",
"tool",
"type"
],
"title": "DynamicToolCallThreadItem",
"type": "object"
},
{
"properties": {
"agentsStates": {