2026-02-01 23:38:43 -08:00
{
"$schema" : "http://json-schema.org/draft-07/schema#" ,
"definitions" : {
2026-02-27 09:42:52 -08:00
"AbsolutePathBuf" : {
"description" : "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute." ,
"type" : "string"
} ,
feat: add experimental additionalPermissions to v2 command execution approval requests (#12737)
This adds additionalPermissions to the app-server v2
item/commandExecution/requestApproval payload as an experimental field.
The field is now exposed on CommandExecutionRequestApprovalParams and is
populated from the existing core approval event when a command requests
additional sandbox permissions.
This PR also contains changes to make server requests to support
experiment API.
A real app server test client test:
sample payload with experimental flag off:
```
{
< "id": 0,
< "method": "item/commandExecution/requestApproval",
< "params": {
< "command": "/bin/zsh -lc 'mkdir -p ~/some/test && touch ~/some/test/file'",
< "commandActions": [
< {
< "command": "mkdir -p '~/some/test'",
< "type": "unknown"
< },
< {
< "command": "touch '~/some/test/file'",
< "type": "unknown"
< }
< ],
< "cwd": "/Users/celia/code/codex/codex-rs",
< "itemId": "call_QLp0LWkQ1XkU6VW9T2vUZFWB",
< "proposedExecpolicyAmendment": [
< "mkdir",
< "-p",
< "~/some/test"
< ],
< "reason": "Do you want to allow creating ~/some/test/file outside the workspace?",
< "threadId": "019c9309-e209-7d82-a01b-dcf9556a354d",
< "turnId": "019c9309-e27a-7f33-834f-6011e795c2d6"
< }
< }
```
with experimental flag on:
```
< {
< "id": 0,
< "method": "item/commandExecution/requestApproval",
< "params": {
< "additionalPermissions": {
< "fileSystem": null,
< "macos": null,
< "network": true
< },
< "command": "/bin/zsh -lc 'install -D /dev/null ~/some/test/file'",
< "commandActions": [
< {
< "command": "install -D /dev/null '~/some/test/file'",
< "type": "unknown"
< }
< ],
< "cwd": "/Users/celia/code/codex/codex-rs",
< "itemId": "call_K3U4b3dRbj3eMCqslmncbGsq",
< "proposedExecpolicyAmendment": [
< "install",
< "-D"
< ],
< "reason": "Do you want to allow creating the file at ~/some/test/file outside the workspace sandbox?",
< "threadId": "019c9303-3a8e-76e1-81bf-d67ac446d892",
< "turnId": "019c9303-3af1-7143-88a1-73132f771234"
< }
< }
```
2026-02-24 21:16:35 -08:00
"AdditionalFileSystemPermissions" : {
"properties" : {
"read" : {
"items" : {
2026-02-27 09:42:52 -08:00
"$ref" : "#/definitions/AbsolutePathBuf"
feat: add experimental additionalPermissions to v2 command execution approval requests (#12737)
This adds additionalPermissions to the app-server v2
item/commandExecution/requestApproval payload as an experimental field.
The field is now exposed on CommandExecutionRequestApprovalParams and is
populated from the existing core approval event when a command requests
additional sandbox permissions.
This PR also contains changes to make server requests to support
experiment API.
A real app server test client test:
sample payload with experimental flag off:
```
{
< "id": 0,
< "method": "item/commandExecution/requestApproval",
< "params": {
< "command": "/bin/zsh -lc 'mkdir -p ~/some/test && touch ~/some/test/file'",
< "commandActions": [
< {
< "command": "mkdir -p '~/some/test'",
< "type": "unknown"
< },
< {
< "command": "touch '~/some/test/file'",
< "type": "unknown"
< }
< ],
< "cwd": "/Users/celia/code/codex/codex-rs",
< "itemId": "call_QLp0LWkQ1XkU6VW9T2vUZFWB",
< "proposedExecpolicyAmendment": [
< "mkdir",
< "-p",
< "~/some/test"
< ],
< "reason": "Do you want to allow creating ~/some/test/file outside the workspace?",
< "threadId": "019c9309-e209-7d82-a01b-dcf9556a354d",
< "turnId": "019c9309-e27a-7f33-834f-6011e795c2d6"
< }
< }
```
with experimental flag on:
```
< {
< "id": 0,
< "method": "item/commandExecution/requestApproval",
< "params": {
< "additionalPermissions": {
< "fileSystem": null,
< "macos": null,
< "network": true
< },
< "command": "/bin/zsh -lc 'install -D /dev/null ~/some/test/file'",
< "commandActions": [
< {
< "command": "install -D /dev/null '~/some/test/file'",
< "type": "unknown"
< }
< ],
< "cwd": "/Users/celia/code/codex/codex-rs",
< "itemId": "call_K3U4b3dRbj3eMCqslmncbGsq",
< "proposedExecpolicyAmendment": [
< "install",
< "-D"
< ],
< "reason": "Do you want to allow creating the file at ~/some/test/file outside the workspace sandbox?",
< "threadId": "019c9303-3a8e-76e1-81bf-d67ac446d892",
< "turnId": "019c9303-3af1-7143-88a1-73132f771234"
< }
< }
```
2026-02-24 21:16:35 -08:00
} ,
"type" : [
"array" ,
"null"
]
} ,
"write" : {
"items" : {
2026-02-27 09:42:52 -08:00
"$ref" : "#/definitions/AbsolutePathBuf"
feat: add experimental additionalPermissions to v2 command execution approval requests (#12737)
This adds additionalPermissions to the app-server v2
item/commandExecution/requestApproval payload as an experimental field.
The field is now exposed on CommandExecutionRequestApprovalParams and is
populated from the existing core approval event when a command requests
additional sandbox permissions.
This PR also contains changes to make server requests to support
experiment API.
A real app server test client test:
sample payload with experimental flag off:
```
{
< "id": 0,
< "method": "item/commandExecution/requestApproval",
< "params": {
< "command": "/bin/zsh -lc 'mkdir -p ~/some/test && touch ~/some/test/file'",
< "commandActions": [
< {
< "command": "mkdir -p '~/some/test'",
< "type": "unknown"
< },
< {
< "command": "touch '~/some/test/file'",
< "type": "unknown"
< }
< ],
< "cwd": "/Users/celia/code/codex/codex-rs",
< "itemId": "call_QLp0LWkQ1XkU6VW9T2vUZFWB",
< "proposedExecpolicyAmendment": [
< "mkdir",
< "-p",
< "~/some/test"
< ],
< "reason": "Do you want to allow creating ~/some/test/file outside the workspace?",
< "threadId": "019c9309-e209-7d82-a01b-dcf9556a354d",
< "turnId": "019c9309-e27a-7f33-834f-6011e795c2d6"
< }
< }
```
with experimental flag on:
```
< {
< "id": 0,
< "method": "item/commandExecution/requestApproval",
< "params": {
< "additionalPermissions": {
< "fileSystem": null,
< "macos": null,
< "network": true
< },
< "command": "/bin/zsh -lc 'install -D /dev/null ~/some/test/file'",
< "commandActions": [
< {
< "command": "install -D /dev/null '~/some/test/file'",
< "type": "unknown"
< }
< ],
< "cwd": "/Users/celia/code/codex/codex-rs",
< "itemId": "call_K3U4b3dRbj3eMCqslmncbGsq",
< "proposedExecpolicyAmendment": [
< "install",
< "-D"
< ],
< "reason": "Do you want to allow creating the file at ~/some/test/file outside the workspace sandbox?",
< "threadId": "019c9303-3a8e-76e1-81bf-d67ac446d892",
< "turnId": "019c9303-3af1-7143-88a1-73132f771234"
< }
< }
```
2026-02-24 21:16:35 -08:00
} ,
"type" : [
"array" ,
"null"
]
}
} ,
"type" : "object"
} ,
"AdditionalMacOsPermissions" : {
"properties" : {
"accessibility" : {
2026-03-05 16:21:45 -08:00
"type" : "boolean"
feat: add experimental additionalPermissions to v2 command execution approval requests (#12737)
This adds additionalPermissions to the app-server v2
item/commandExecution/requestApproval payload as an experimental field.
The field is now exposed on CommandExecutionRequestApprovalParams and is
populated from the existing core approval event when a command requests
additional sandbox permissions.
This PR also contains changes to make server requests to support
experiment API.
A real app server test client test:
sample payload with experimental flag off:
```
{
< "id": 0,
< "method": "item/commandExecution/requestApproval",
< "params": {
< "command": "/bin/zsh -lc 'mkdir -p ~/some/test && touch ~/some/test/file'",
< "commandActions": [
< {
< "command": "mkdir -p '~/some/test'",
< "type": "unknown"
< },
< {
< "command": "touch '~/some/test/file'",
< "type": "unknown"
< }
< ],
< "cwd": "/Users/celia/code/codex/codex-rs",
< "itemId": "call_QLp0LWkQ1XkU6VW9T2vUZFWB",
< "proposedExecpolicyAmendment": [
< "mkdir",
< "-p",
< "~/some/test"
< ],
< "reason": "Do you want to allow creating ~/some/test/file outside the workspace?",
< "threadId": "019c9309-e209-7d82-a01b-dcf9556a354d",
< "turnId": "019c9309-e27a-7f33-834f-6011e795c2d6"
< }
< }
```
with experimental flag on:
```
< {
< "id": 0,
< "method": "item/commandExecution/requestApproval",
< "params": {
< "additionalPermissions": {
< "fileSystem": null,
< "macos": null,
< "network": true
< },
< "command": "/bin/zsh -lc 'install -D /dev/null ~/some/test/file'",
< "commandActions": [
< {
< "command": "install -D /dev/null '~/some/test/file'",
< "type": "unknown"
< }
< ],
< "cwd": "/Users/celia/code/codex/codex-rs",
< "itemId": "call_K3U4b3dRbj3eMCqslmncbGsq",
< "proposedExecpolicyAmendment": [
< "install",
< "-D"
< ],
< "reason": "Do you want to allow creating the file at ~/some/test/file outside the workspace sandbox?",
< "threadId": "019c9303-3a8e-76e1-81bf-d67ac446d892",
< "turnId": "019c9303-3af1-7143-88a1-73132f771234"
< }
< }
```
2026-02-24 21:16:35 -08:00
} ,
"automations" : {
2026-03-05 16:21:45 -08:00
"$ref" : "#/definitions/MacOsAutomationPermission"
feat: add experimental additionalPermissions to v2 command execution approval requests (#12737)
This adds additionalPermissions to the app-server v2
item/commandExecution/requestApproval payload as an experimental field.
The field is now exposed on CommandExecutionRequestApprovalParams and is
populated from the existing core approval event when a command requests
additional sandbox permissions.
This PR also contains changes to make server requests to support
experiment API.
A real app server test client test:
sample payload with experimental flag off:
```
{
< "id": 0,
< "method": "item/commandExecution/requestApproval",
< "params": {
< "command": "/bin/zsh -lc 'mkdir -p ~/some/test && touch ~/some/test/file'",
< "commandActions": [
< {
< "command": "mkdir -p '~/some/test'",
< "type": "unknown"
< },
< {
< "command": "touch '~/some/test/file'",
< "type": "unknown"
< }
< ],
< "cwd": "/Users/celia/code/codex/codex-rs",
< "itemId": "call_QLp0LWkQ1XkU6VW9T2vUZFWB",
< "proposedExecpolicyAmendment": [
< "mkdir",
< "-p",
< "~/some/test"
< ],
< "reason": "Do you want to allow creating ~/some/test/file outside the workspace?",
< "threadId": "019c9309-e209-7d82-a01b-dcf9556a354d",
< "turnId": "019c9309-e27a-7f33-834f-6011e795c2d6"
< }
< }
```
with experimental flag on:
```
< {
< "id": 0,
< "method": "item/commandExecution/requestApproval",
< "params": {
< "additionalPermissions": {
< "fileSystem": null,
< "macos": null,
< "network": true
< },
< "command": "/bin/zsh -lc 'install -D /dev/null ~/some/test/file'",
< "commandActions": [
< {
< "command": "install -D /dev/null '~/some/test/file'",
< "type": "unknown"
< }
< ],
< "cwd": "/Users/celia/code/codex/codex-rs",
< "itemId": "call_K3U4b3dRbj3eMCqslmncbGsq",
< "proposedExecpolicyAmendment": [
< "install",
< "-D"
< ],
< "reason": "Do you want to allow creating the file at ~/some/test/file outside the workspace sandbox?",
< "threadId": "019c9303-3a8e-76e1-81bf-d67ac446d892",
< "turnId": "019c9303-3af1-7143-88a1-73132f771234"
< }
< }
```
2026-02-24 21:16:35 -08:00
} ,
"calendar" : {
2026-03-05 16:21:45 -08:00
"type" : "boolean"
feat: add experimental additionalPermissions to v2 command execution approval requests (#12737)
This adds additionalPermissions to the app-server v2
item/commandExecution/requestApproval payload as an experimental field.
The field is now exposed on CommandExecutionRequestApprovalParams and is
populated from the existing core approval event when a command requests
additional sandbox permissions.
This PR also contains changes to make server requests to support
experiment API.
A real app server test client test:
sample payload with experimental flag off:
```
{
< "id": 0,
< "method": "item/commandExecution/requestApproval",
< "params": {
< "command": "/bin/zsh -lc 'mkdir -p ~/some/test && touch ~/some/test/file'",
< "commandActions": [
< {
< "command": "mkdir -p '~/some/test'",
< "type": "unknown"
< },
< {
< "command": "touch '~/some/test/file'",
< "type": "unknown"
< }
< ],
< "cwd": "/Users/celia/code/codex/codex-rs",
< "itemId": "call_QLp0LWkQ1XkU6VW9T2vUZFWB",
< "proposedExecpolicyAmendment": [
< "mkdir",
< "-p",
< "~/some/test"
< ],
< "reason": "Do you want to allow creating ~/some/test/file outside the workspace?",
< "threadId": "019c9309-e209-7d82-a01b-dcf9556a354d",
< "turnId": "019c9309-e27a-7f33-834f-6011e795c2d6"
< }
< }
```
with experimental flag on:
```
< {
< "id": 0,
< "method": "item/commandExecution/requestApproval",
< "params": {
< "additionalPermissions": {
< "fileSystem": null,
< "macos": null,
< "network": true
< },
< "command": "/bin/zsh -lc 'install -D /dev/null ~/some/test/file'",
< "commandActions": [
< {
< "command": "install -D /dev/null '~/some/test/file'",
< "type": "unknown"
< }
< ],
< "cwd": "/Users/celia/code/codex/codex-rs",
< "itemId": "call_K3U4b3dRbj3eMCqslmncbGsq",
< "proposedExecpolicyAmendment": [
< "install",
< "-D"
< ],
< "reason": "Do you want to allow creating the file at ~/some/test/file outside the workspace sandbox?",
< "threadId": "019c9303-3a8e-76e1-81bf-d67ac446d892",
< "turnId": "019c9303-3af1-7143-88a1-73132f771234"
< }
< }
```
2026-02-24 21:16:35 -08:00
} ,
2026-03-10 16:34:47 -07:00
"contacts" : {
"$ref" : "#/definitions/MacOsContactsPermission"
} ,
"launchServices" : {
"type" : "boolean"
} ,
feat: add experimental additionalPermissions to v2 command execution approval requests (#12737)
This adds additionalPermissions to the app-server v2
item/commandExecution/requestApproval payload as an experimental field.
The field is now exposed on CommandExecutionRequestApprovalParams and is
populated from the existing core approval event when a command requests
additional sandbox permissions.
This PR also contains changes to make server requests to support
experiment API.
A real app server test client test:
sample payload with experimental flag off:
```
{
< "id": 0,
< "method": "item/commandExecution/requestApproval",
< "params": {
< "command": "/bin/zsh -lc 'mkdir -p ~/some/test && touch ~/some/test/file'",
< "commandActions": [
< {
< "command": "mkdir -p '~/some/test'",
< "type": "unknown"
< },
< {
< "command": "touch '~/some/test/file'",
< "type": "unknown"
< }
< ],
< "cwd": "/Users/celia/code/codex/codex-rs",
< "itemId": "call_QLp0LWkQ1XkU6VW9T2vUZFWB",
< "proposedExecpolicyAmendment": [
< "mkdir",
< "-p",
< "~/some/test"
< ],
< "reason": "Do you want to allow creating ~/some/test/file outside the workspace?",
< "threadId": "019c9309-e209-7d82-a01b-dcf9556a354d",
< "turnId": "019c9309-e27a-7f33-834f-6011e795c2d6"
< }
< }
```
with experimental flag on:
```
< {
< "id": 0,
< "method": "item/commandExecution/requestApproval",
< "params": {
< "additionalPermissions": {
< "fileSystem": null,
< "macos": null,
< "network": true
< },
< "command": "/bin/zsh -lc 'install -D /dev/null ~/some/test/file'",
< "commandActions": [
< {
< "command": "install -D /dev/null '~/some/test/file'",
< "type": "unknown"
< }
< ],
< "cwd": "/Users/celia/code/codex/codex-rs",
< "itemId": "call_K3U4b3dRbj3eMCqslmncbGsq",
< "proposedExecpolicyAmendment": [
< "install",
< "-D"
< ],
< "reason": "Do you want to allow creating the file at ~/some/test/file outside the workspace sandbox?",
< "threadId": "019c9303-3a8e-76e1-81bf-d67ac446d892",
< "turnId": "019c9303-3af1-7143-88a1-73132f771234"
< }
< }
```
2026-02-24 21:16:35 -08:00
"preferences" : {
2026-03-05 16:21:45 -08:00
"$ref" : "#/definitions/MacOsPreferencesPermission"
2026-03-10 16:34:47 -07:00
} ,
"reminders" : {
"type" : "boolean"
feat: add experimental additionalPermissions to v2 command execution approval requests (#12737)
This adds additionalPermissions to the app-server v2
item/commandExecution/requestApproval payload as an experimental field.
The field is now exposed on CommandExecutionRequestApprovalParams and is
populated from the existing core approval event when a command requests
additional sandbox permissions.
This PR also contains changes to make server requests to support
experiment API.
A real app server test client test:
sample payload with experimental flag off:
```
{
< "id": 0,
< "method": "item/commandExecution/requestApproval",
< "params": {
< "command": "/bin/zsh -lc 'mkdir -p ~/some/test && touch ~/some/test/file'",
< "commandActions": [
< {
< "command": "mkdir -p '~/some/test'",
< "type": "unknown"
< },
< {
< "command": "touch '~/some/test/file'",
< "type": "unknown"
< }
< ],
< "cwd": "/Users/celia/code/codex/codex-rs",
< "itemId": "call_QLp0LWkQ1XkU6VW9T2vUZFWB",
< "proposedExecpolicyAmendment": [
< "mkdir",
< "-p",
< "~/some/test"
< ],
< "reason": "Do you want to allow creating ~/some/test/file outside the workspace?",
< "threadId": "019c9309-e209-7d82-a01b-dcf9556a354d",
< "turnId": "019c9309-e27a-7f33-834f-6011e795c2d6"
< }
< }
```
with experimental flag on:
```
< {
< "id": 0,
< "method": "item/commandExecution/requestApproval",
< "params": {
< "additionalPermissions": {
< "fileSystem": null,
< "macos": null,
< "network": true
< },
< "command": "/bin/zsh -lc 'install -D /dev/null ~/some/test/file'",
< "commandActions": [
< {
< "command": "install -D /dev/null '~/some/test/file'",
< "type": "unknown"
< }
< ],
< "cwd": "/Users/celia/code/codex/codex-rs",
< "itemId": "call_K3U4b3dRbj3eMCqslmncbGsq",
< "proposedExecpolicyAmendment": [
< "install",
< "-D"
< ],
< "reason": "Do you want to allow creating the file at ~/some/test/file outside the workspace sandbox?",
< "threadId": "019c9303-3a8e-76e1-81bf-d67ac446d892",
< "turnId": "019c9303-3af1-7143-88a1-73132f771234"
< }
< }
```
2026-02-24 21:16:35 -08:00
}
} ,
2026-03-05 16:21:45 -08:00
"required" : [
"accessibility" ,
"automations" ,
"calendar" ,
2026-03-10 16:34:47 -07:00
"contacts" ,
"launchServices" ,
"preferences" ,
"reminders"
2026-03-05 16:21:45 -08:00
] ,
feat: add experimental additionalPermissions to v2 command execution approval requests (#12737)
This adds additionalPermissions to the app-server v2
item/commandExecution/requestApproval payload as an experimental field.
The field is now exposed on CommandExecutionRequestApprovalParams and is
populated from the existing core approval event when a command requests
additional sandbox permissions.
This PR also contains changes to make server requests to support
experiment API.
A real app server test client test:
sample payload with experimental flag off:
```
{
< "id": 0,
< "method": "item/commandExecution/requestApproval",
< "params": {
< "command": "/bin/zsh -lc 'mkdir -p ~/some/test && touch ~/some/test/file'",
< "commandActions": [
< {
< "command": "mkdir -p '~/some/test'",
< "type": "unknown"
< },
< {
< "command": "touch '~/some/test/file'",
< "type": "unknown"
< }
< ],
< "cwd": "/Users/celia/code/codex/codex-rs",
< "itemId": "call_QLp0LWkQ1XkU6VW9T2vUZFWB",
< "proposedExecpolicyAmendment": [
< "mkdir",
< "-p",
< "~/some/test"
< ],
< "reason": "Do you want to allow creating ~/some/test/file outside the workspace?",
< "threadId": "019c9309-e209-7d82-a01b-dcf9556a354d",
< "turnId": "019c9309-e27a-7f33-834f-6011e795c2d6"
< }
< }
```
with experimental flag on:
```
< {
< "id": 0,
< "method": "item/commandExecution/requestApproval",
< "params": {
< "additionalPermissions": {
< "fileSystem": null,
< "macos": null,
< "network": true
< },
< "command": "/bin/zsh -lc 'install -D /dev/null ~/some/test/file'",
< "commandActions": [
< {
< "command": "install -D /dev/null '~/some/test/file'",
< "type": "unknown"
< }
< ],
< "cwd": "/Users/celia/code/codex/codex-rs",
< "itemId": "call_K3U4b3dRbj3eMCqslmncbGsq",
< "proposedExecpolicyAmendment": [
< "install",
< "-D"
< ],
< "reason": "Do you want to allow creating the file at ~/some/test/file outside the workspace sandbox?",
< "threadId": "019c9303-3a8e-76e1-81bf-d67ac446d892",
< "turnId": "019c9303-3af1-7143-88a1-73132f771234"
< }
< }
```
2026-02-24 21:16:35 -08:00
"type" : "object"
} ,
2026-03-03 20:57:29 -08:00
"AdditionalNetworkPermissions" : {
"properties" : {
"enabled" : {
"type" : [
"boolean" ,
"null"
]
}
} ,
"type" : "object"
} ,
feat: add experimental additionalPermissions to v2 command execution approval requests (#12737)
This adds additionalPermissions to the app-server v2
item/commandExecution/requestApproval payload as an experimental field.
The field is now exposed on CommandExecutionRequestApprovalParams and is
populated from the existing core approval event when a command requests
additional sandbox permissions.
This PR also contains changes to make server requests to support
experiment API.
A real app server test client test:
sample payload with experimental flag off:
```
{
< "id": 0,
< "method": "item/commandExecution/requestApproval",
< "params": {
< "command": "/bin/zsh -lc 'mkdir -p ~/some/test && touch ~/some/test/file'",
< "commandActions": [
< {
< "command": "mkdir -p '~/some/test'",
< "type": "unknown"
< },
< {
< "command": "touch '~/some/test/file'",
< "type": "unknown"
< }
< ],
< "cwd": "/Users/celia/code/codex/codex-rs",
< "itemId": "call_QLp0LWkQ1XkU6VW9T2vUZFWB",
< "proposedExecpolicyAmendment": [
< "mkdir",
< "-p",
< "~/some/test"
< ],
< "reason": "Do you want to allow creating ~/some/test/file outside the workspace?",
< "threadId": "019c9309-e209-7d82-a01b-dcf9556a354d",
< "turnId": "019c9309-e27a-7f33-834f-6011e795c2d6"
< }
< }
```
with experimental flag on:
```
< {
< "id": 0,
< "method": "item/commandExecution/requestApproval",
< "params": {
< "additionalPermissions": {
< "fileSystem": null,
< "macos": null,
< "network": true
< },
< "command": "/bin/zsh -lc 'install -D /dev/null ~/some/test/file'",
< "commandActions": [
< {
< "command": "install -D /dev/null '~/some/test/file'",
< "type": "unknown"
< }
< ],
< "cwd": "/Users/celia/code/codex/codex-rs",
< "itemId": "call_K3U4b3dRbj3eMCqslmncbGsq",
< "proposedExecpolicyAmendment": [
< "install",
< "-D"
< ],
< "reason": "Do you want to allow creating the file at ~/some/test/file outside the workspace sandbox?",
< "threadId": "019c9303-3a8e-76e1-81bf-d67ac446d892",
< "turnId": "019c9303-3af1-7143-88a1-73132f771234"
< }
< }
```
2026-02-24 21:16:35 -08:00
"AdditionalPermissionProfile" : {
"properties" : {
"fileSystem" : {
"anyOf" : [
{
"$ref" : "#/definitions/AdditionalFileSystemPermissions"
} ,
{
"type" : "null"
}
]
} ,
"macos" : {
"anyOf" : [
{
"$ref" : "#/definitions/AdditionalMacOsPermissions"
} ,
{
"type" : "null"
}
]
} ,
"network" : {
2026-03-03 20:57:29 -08:00
"anyOf" : [
{
"$ref" : "#/definitions/AdditionalNetworkPermissions"
} ,
{
"type" : "null"
}
feat: add experimental additionalPermissions to v2 command execution approval requests (#12737)
This adds additionalPermissions to the app-server v2
item/commandExecution/requestApproval payload as an experimental field.
The field is now exposed on CommandExecutionRequestApprovalParams and is
populated from the existing core approval event when a command requests
additional sandbox permissions.
This PR also contains changes to make server requests to support
experiment API.
A real app server test client test:
sample payload with experimental flag off:
```
{
< "id": 0,
< "method": "item/commandExecution/requestApproval",
< "params": {
< "command": "/bin/zsh -lc 'mkdir -p ~/some/test && touch ~/some/test/file'",
< "commandActions": [
< {
< "command": "mkdir -p '~/some/test'",
< "type": "unknown"
< },
< {
< "command": "touch '~/some/test/file'",
< "type": "unknown"
< }
< ],
< "cwd": "/Users/celia/code/codex/codex-rs",
< "itemId": "call_QLp0LWkQ1XkU6VW9T2vUZFWB",
< "proposedExecpolicyAmendment": [
< "mkdir",
< "-p",
< "~/some/test"
< ],
< "reason": "Do you want to allow creating ~/some/test/file outside the workspace?",
< "threadId": "019c9309-e209-7d82-a01b-dcf9556a354d",
< "turnId": "019c9309-e27a-7f33-834f-6011e795c2d6"
< }
< }
```
with experimental flag on:
```
< {
< "id": 0,
< "method": "item/commandExecution/requestApproval",
< "params": {
< "additionalPermissions": {
< "fileSystem": null,
< "macos": null,
< "network": true
< },
< "command": "/bin/zsh -lc 'install -D /dev/null ~/some/test/file'",
< "commandActions": [
< {
< "command": "install -D /dev/null '~/some/test/file'",
< "type": "unknown"
< }
< ],
< "cwd": "/Users/celia/code/codex/codex-rs",
< "itemId": "call_K3U4b3dRbj3eMCqslmncbGsq",
< "proposedExecpolicyAmendment": [
< "install",
< "-D"
< ],
< "reason": "Do you want to allow creating the file at ~/some/test/file outside the workspace sandbox?",
< "threadId": "019c9303-3a8e-76e1-81bf-d67ac446d892",
< "turnId": "019c9303-3af1-7143-88a1-73132f771234"
< }
< }
```
2026-02-24 21:16:35 -08:00
]
}
} ,
"type" : "object"
} ,
2026-02-01 23:38:43 -08:00
"ApplyPatchApprovalParams" : {
"properties" : {
"callId" : {
2026-02-20 23:45:35 -08:00
"description" : "Use to correlate this with [codex_protocol::protocol::PatchApplyBeginEvent] and [codex_protocol::protocol::PatchApplyEndEvent]." ,
2026-02-01 23:38:43 -08:00
"type" : "string"
} ,
"conversationId" : {
"$ref" : "#/definitions/ThreadId"
} ,
"fileChanges" : {
"additionalProperties" : {
"$ref" : "#/definitions/FileChange"
} ,
"type" : "object"
} ,
"grantRoot" : {
"description" : "When set, the agent is asking the user to allow writes under this root for the remainder of the session (unclear if this is honored today)." ,
"type" : [
"string" ,
"null"
]
} ,
"reason" : {
"description" : "Optional explanatory reason (e.g. request for extra write access)." ,
"type" : [
"string" ,
"null"
]
}
} ,
"required" : [
"callId" ,
"conversationId" ,
"fileChanges"
] ,
"type" : "object"
} ,
"ChatgptAuthTokensRefreshParams" : {
"properties" : {
"previousAccountId" : {
2026-02-09 20:48:58 -08:00
"description" : "Workspace/account identifier that Codex was previously using.\n\nClients that manage multiple accounts/workspaces can use this as a hint to refresh the token for the correct workspace.\n\nThis may be `null` when the prior auth state did not include a workspace identifier (`chatgpt_account_id`)." ,
2026-02-01 23:38:43 -08:00
"type" : [
"string" ,
"null"
]
} ,
"reason" : {
"$ref" : "#/definitions/ChatgptAuthTokensRefreshReason"
}
} ,
"required" : [
"reason"
] ,
"type" : "object"
} ,
"ChatgptAuthTokensRefreshReason" : {
"oneOf" : [
{
"description" : "Codex attempted a backend request and received `401 Unauthorized`." ,
"enum" : [
"unauthorized"
] ,
"type" : "string"
}
]
} ,
"CommandAction" : {
"oneOf" : [
{
"properties" : {
"command" : {
"type" : "string"
} ,
"name" : {
"type" : "string"
} ,
"path" : {
"type" : "string"
} ,
"type" : {
"enum" : [
"read"
] ,
"title" : "ReadCommandActionType" ,
"type" : "string"
}
} ,
"required" : [
"command" ,
"name" ,
"path" ,
"type"
] ,
"title" : "ReadCommandAction" ,
"type" : "object"
} ,
{
"properties" : {
"command" : {
"type" : "string"
} ,
"path" : {
"type" : [
"string" ,
"null"
]
} ,
"type" : {
"enum" : [
"listFiles"
] ,
"title" : "ListFilesCommandActionType" ,
"type" : "string"
}
} ,
"required" : [
"command" ,
"type"
] ,
"title" : "ListFilesCommandAction" ,
"type" : "object"
} ,
{
"properties" : {
"command" : {
"type" : "string"
} ,
"path" : {
"type" : [
"string" ,
"null"
]
} ,
"query" : {
"type" : [
"string" ,
"null"
]
} ,
"type" : {
"enum" : [
"search"
] ,
"title" : "SearchCommandActionType" ,
"type" : "string"
}
} ,
"required" : [
"command" ,
"type"
] ,
"title" : "SearchCommandAction" ,
"type" : "object"
} ,
{
"properties" : {
"command" : {
"type" : "string"
} ,
"type" : {
"enum" : [
"unknown"
] ,
"title" : "UnknownCommandActionType" ,
"type" : "string"
}
} ,
"required" : [
"command" ,
"type"
] ,
"title" : "UnknownCommandAction" ,
"type" : "object"
}
]
} ,
feat: include available decisions in command approval requests (#12758)
Command-approval clients currently infer which choices to show from
side-channel fields like `networkApprovalContext`,
`proposedExecpolicyAmendment`, and `additionalPermissions`. That makes
the request shape harder to evolve, and it forces each client to
replicate the server's heuristics instead of receiving the exact
decision list for the prompt.
This PR introduces a mapping between `CommandExecutionApprovalDecision`
and `codex_protocol::protocol::ReviewDecision`:
```rust
impl From<CoreReviewDecision> for CommandExecutionApprovalDecision {
fn from(value: CoreReviewDecision) -> Self {
match value {
CoreReviewDecision::Approved => Self::Accept,
CoreReviewDecision::ApprovedExecpolicyAmendment {
proposed_execpolicy_amendment,
} => Self::AcceptWithExecpolicyAmendment {
execpolicy_amendment: proposed_execpolicy_amendment.into(),
},
CoreReviewDecision::ApprovedForSession => Self::AcceptForSession,
CoreReviewDecision::NetworkPolicyAmendment {
network_policy_amendment,
} => Self::ApplyNetworkPolicyAmendment {
network_policy_amendment: network_policy_amendment.into(),
},
CoreReviewDecision::Abort => Self::Cancel,
CoreReviewDecision::Denied => Self::Decline,
}
}
}
```
And updates `CommandExecutionRequestApprovalParams` to have a new field:
```rust
available_decisions: Option<Vec<CommandExecutionApprovalDecision>>
```
when, if specified, should make it easier for clients to display an
appropriate list of options in the UI.
This makes it possible for `CoreShellActionProvider::prompt()` in
`unix_escalation.rs` to specify the `Vec<ReviewDecision>` directly,
adding support for `ApprovedForSession` when approving a skill script,
which was previously missing in the TUI.
Note this results in a significant change to `exec_options()` in
`approval_overlay.rs`, as the displayed options are now derived from
`available_decisions: &[ReviewDecision]`.
## What Changed
- Add `available_decisions` to
[`ExecApprovalRequestEvent`](https://github.com/openai/codex/blob/de00e932dd9801de0a4faac0519162099753f331/codex-rs/protocol/src/approvals.rs#L111-L175),
including helpers to derive the legacy default choices when older
senders omit the field.
- Map `codex_protocol::protocol::ReviewDecision` to app-server
`CommandExecutionApprovalDecision` and expose the ordered list as
experimental `availableDecisions` in
[`CommandExecutionRequestApprovalParams`](https://github.com/openai/codex/blob/de00e932dd9801de0a4faac0519162099753f331/codex-rs/app-server-protocol/src/protocol/v2.rs#L3798-L3807).
- Thread optional `available_decisions` through the core approval path
so Unix shell escalation can explicitly request `ApprovedForSession` for
session-scoped approvals instead of relying on client heuristics.
[`unix_escalation.rs`](https://github.com/openai/codex/blob/de00e932dd9801de0a4faac0519162099753f331/codex-rs/core/src/tools/runtimes/shell/unix_escalation.rs#L194-L214)
- Update the TUI approval overlay to build its buttons from the ordered
decision list, while preserving the legacy fallback when
`available_decisions` is missing.
- Update the app-server README, test client output, and generated schema
artifacts to document and surface the new field.
## Testing
- Add `approval_overlay.rs` coverage for explicit decision lists,
including the generic `ApprovedForSession` path and network approval
options.
- Update `chatwidget/tests.rs` and app-server protocol tests to populate
the new optional field and keep older event shapes working.
## Developers Docs
- If we document `item/commandExecution/requestApproval` on
[developers.openai.com/codex](https://developers.openai.com/codex), add
experimental `availableDecisions` as the preferred source of approval
choices and note that older servers may omit it.
2026-02-25 17:10:46 -08:00
"CommandExecutionApprovalDecision" : {
"oneOf" : [
{
"description" : "User approved the command." ,
"enum" : [
"accept"
] ,
"type" : "string"
} ,
{
"description" : "User approved the command and future prompts in the same session-scoped approval cache should run without prompting." ,
"enum" : [
"acceptForSession"
] ,
"type" : "string"
} ,
{
"additionalProperties" : false ,
"description" : "User approved the command, and wants to apply the proposed execpolicy amendment so future matching commands can run without prompting." ,
"properties" : {
"acceptWithExecpolicyAmendment" : {
"properties" : {
"execpolicy_amendment" : {
"items" : {
"type" : "string"
} ,
"type" : "array"
}
} ,
"required" : [
"execpolicy_amendment"
] ,
"type" : "object"
}
} ,
"required" : [
"acceptWithExecpolicyAmendment"
] ,
"title" : "AcceptWithExecpolicyAmendmentCommandExecutionApprovalDecision" ,
"type" : "object"
} ,
{
"additionalProperties" : false ,
"description" : "User chose a persistent network policy rule (allow/deny) for this host." ,
"properties" : {
"applyNetworkPolicyAmendment" : {
"properties" : {
"network_policy_amendment" : {
"$ref" : "#/definitions/NetworkPolicyAmendment"
}
} ,
"required" : [
"network_policy_amendment"
] ,
"type" : "object"
}
} ,
"required" : [
"applyNetworkPolicyAmendment"
] ,
"title" : "ApplyNetworkPolicyAmendmentCommandExecutionApprovalDecision" ,
"type" : "object"
} ,
{
"description" : "User denied the command. The agent will continue the turn." ,
"enum" : [
"decline"
] ,
"type" : "string"
} ,
{
"description" : "User denied the command. The turn will also be immediately interrupted." ,
"enum" : [
"cancel"
] ,
"type" : "string"
}
]
} ,
2026-02-01 23:38:43 -08:00
"CommandExecutionRequestApprovalParams" : {
"properties" : {
2026-02-17 17:55:57 -08:00
"approvalId" : {
"description" : "Unique identifier for this specific approval callback.\n\nFor regular shell/unified_exec approvals, this is null.\n\nFor zsh-exec-bridge subcommand approvals, multiple callbacks can belong to one parent `itemId`, so `approvalId` is a distinct opaque callback id (a UUID) used to disambiguate routing." ,
"type" : [
"string" ,
"null"
]
} ,
2026-02-01 23:38:43 -08:00
"command" : {
"description" : "The command to be executed." ,
"type" : [
"string" ,
"null"
]
} ,
"commandActions" : {
"description" : "Best-effort parsed command actions for friendly display." ,
"items" : {
"$ref" : "#/definitions/CommandAction"
} ,
"type" : [
"array" ,
"null"
]
} ,
"cwd" : {
"description" : "The command's working directory." ,
"type" : [
"string" ,
"null"
]
} ,
"itemId" : {
"type" : "string"
} ,
2026-02-20 10:39:55 -08:00
"networkApprovalContext" : {
"anyOf" : [
{
"$ref" : "#/definitions/NetworkApprovalContext"
} ,
{
"type" : "null"
}
] ,
2026-02-24 23:06:19 -08:00
"description" : "Optional context for a managed-network approval prompt."
2026-02-20 10:39:55 -08:00
} ,
2026-02-01 23:38:43 -08:00
"proposedExecpolicyAmendment" : {
"description" : "Optional proposed execpolicy amendment to allow similar commands without prompting." ,
"items" : {
"type" : "string"
} ,
"type" : [
"array" ,
"null"
]
} ,
2026-02-24 23:06:19 -08:00
"proposedNetworkPolicyAmendments" : {
"description" : "Optional proposed network policy amendments (allow/deny host) for future requests." ,
"items" : {
"$ref" : "#/definitions/NetworkPolicyAmendment"
} ,
"type" : [
"array" ,
"null"
]
} ,
2026-02-01 23:38:43 -08:00
"reason" : {
"description" : "Optional explanatory reason (e.g. request for network access)." ,
"type" : [
"string" ,
"null"
]
} ,
"threadId" : {
"type" : "string"
} ,
"turnId" : {
"type" : "string"
}
} ,
"required" : [
"itemId" ,
"threadId" ,
"turnId"
] ,
"type" : "object"
} ,
app-server: include experimental skill metadata in exec approval requests (#13929)
## Summary
This change surfaces skill metadata on command approval requests so
app-server clients can tell when an approval came from a skill script
and identify the originating `SKILL.md`.
- add `skill_metadata` to exec approval events in the shared protocol
- thread skill metadata through core shell escalation and delegated
approval handling for skill-triggered approvals
- expose the field in app-server v2 as experimental `skillMetadata`
- regenerate the JSON/TypeScript schemas and cover the new field in
protocol, transport, core, and TUI tests
## Why
Skill-triggered approvals already carry skill context inside core, but
app-server clients could not see which skill caused the prompt. Sending
the skill metadata with the approval request makes it possible for
clients to present better approval UX and connect the prompt back to the
relevant skill definition.
## example event in app-server-v2
verified that we see this event when experimental api is on:
```
< {
< "id": 11,
< "method": "item/commandExecution/requestApproval",
< "params": {
< "additionalPermissions": {
< "fileSystem": null,
< "macos": {
< "accessibility": false,
< "automations": {
< "bundle_ids": [
< "com.apple.Notes"
< ]
< },
< "calendar": false,
< "preferences": "read_only"
< },
< "network": null
< },
< "approvalId": "25d600ee-5a3c-4746-8d17-e2e61fb4c563",
< "availableDecisions": [
< "accept",
< "acceptForSession",
< "cancel"
< ],
< "command": "/Applications/ChatGPT.app/Contents/Resources/CodexAppServer_CodexAppServerBundledSkills.bundle/Contents/Resources/skills/apple-notes/scripts/notes_info",
< "commandActions": [
< {
< "command": "/Applications/ChatGPT.app/Contents/Resources/CodexAppServer_CodexAppServerBundledSkills.bundle/Contents/Resources/skills/apple-notes/scripts/notes_info",
< "type": "unknown"
< }
< ],
< "cwd": "/Applications/ChatGPT.app/Contents/Resources/CodexAppServer_CodexAppServerBundledSkills.bundle/Contents/Resources/skills/apple-notes",
< "itemId": "call_jZp3xFpNg4D8iKAD49cvEvZy",
< "skillMetadata": {
< "pathToSkillsMd": "/Applications/ChatGPT.app/Contents/Resources/CodexAppServer_CodexAppServerBundledSkills.bundle/Contents/Resources/skills/apple-notes/SKILL.md"
< },
< "threadId": "019ccc10-b7d3-7ff2-84fe-3a75e7681e69",
< "turnId": "019ccc10-b848-76f1-81b3-4a1fa225493f"
< }
< }`
```
& verified that this is the event when experimental api is off:
```
< {
< "id": 13,
< "method": "item/commandExecution/requestApproval",
< "params": {
< "approvalId": "5fbbf776-261b-4cf8-899b-c125b547f2c0",
< "availableDecisions": [
< "accept",
< "acceptForSession",
< "cancel"
< ],
< "command": "/Applications/ChatGPT.app/Contents/Resources/CodexAppServer_CodexAppServerBundledSkills.bundle/Contents/Resources/skills/apple-notes/scripts/notes_info",
< "commandActions": [
< {
< "command": "/Applications/ChatGPT.app/Contents/Resources/CodexAppServer_CodexAppServerBundledSkills.bundle/Contents/Resources/skills/apple-notes/scripts/notes_info",
< "type": "unknown"
< }
< ],
< "cwd": "/Users/celia/code/codex/codex-rs",
< "itemId": "call_OV2DHzTgYcbYtWaTTBWlocOt",
< "threadId": "019ccc16-2a2b-7be1-8500-e00d45b892d4",
< "turnId": "019ccc16-2a8e-7961-98ec-649600e7d06a"
< }
< }
```
2026-03-08 18:07:46 -07:00
"CommandExecutionRequestApprovalSkillMetadata" : {
"properties" : {
"pathToSkillsMd" : {
"type" : "string"
}
} ,
"required" : [
"pathToSkillsMd"
] ,
"type" : "object"
} ,
2026-02-01 23:38:43 -08:00
"DynamicToolCallParams" : {
"properties" : {
"arguments" : true ,
"callId" : {
"type" : "string"
} ,
"threadId" : {
"type" : "string"
} ,
"tool" : {
"type" : "string"
} ,
"turnId" : {
"type" : "string"
}
} ,
"required" : [
"arguments" ,
"callId" ,
"threadId" ,
"tool" ,
"turnId"
] ,
"type" : "object"
} ,
"ExecCommandApprovalParams" : {
"properties" : {
2026-02-17 17:55:57 -08:00
"approvalId" : {
"description" : "Identifier for this specific approval callback." ,
"type" : [
"string" ,
"null"
]
} ,
2026-02-01 23:38:43 -08:00
"callId" : {
2026-02-20 23:45:35 -08:00
"description" : "Use to correlate this with [codex_protocol::protocol::ExecCommandBeginEvent] and [codex_protocol::protocol::ExecCommandEndEvent]." ,
2026-02-01 23:38:43 -08:00
"type" : "string"
} ,
"command" : {
"items" : {
"type" : "string"
} ,
"type" : "array"
} ,
"conversationId" : {
"$ref" : "#/definitions/ThreadId"
} ,
"cwd" : {
"type" : "string"
} ,
"parsedCmd" : {
"items" : {
"$ref" : "#/definitions/ParsedCommand"
} ,
"type" : "array"
} ,
"reason" : {
"type" : [
"string" ,
"null"
]
}
} ,
"required" : [
"callId" ,
"command" ,
"conversationId" ,
"cwd" ,
"parsedCmd"
] ,
"type" : "object"
} ,
"FileChange" : {
"oneOf" : [
{
"properties" : {
"content" : {
"type" : "string"
} ,
"type" : {
"enum" : [
"add"
] ,
"title" : "AddFileChangeType" ,
"type" : "string"
}
} ,
"required" : [
"content" ,
"type"
] ,
"title" : "AddFileChange" ,
"type" : "object"
} ,
{
"properties" : {
"content" : {
"type" : "string"
} ,
"type" : {
"enum" : [
"delete"
] ,
"title" : "DeleteFileChangeType" ,
"type" : "string"
}
} ,
"required" : [
"content" ,
"type"
] ,
"title" : "DeleteFileChange" ,
"type" : "object"
} ,
{
"properties" : {
"move_path" : {
"type" : [
"string" ,
"null"
]
} ,
"type" : {
"enum" : [
"update"
] ,
"title" : "UpdateFileChangeType" ,
"type" : "string"
} ,
"unified_diff" : {
"type" : "string"
}
} ,
"required" : [
"type" ,
"unified_diff"
] ,
"title" : "UpdateFileChange" ,
"type" : "object"
}
]
} ,
"FileChangeRequestApprovalParams" : {
"properties" : {
"grantRoot" : {
"description" : "[UNSTABLE] When set, the agent is asking the user to allow writes under this root for the remainder of the session (unclear if this is honored today)." ,
"type" : [
"string" ,
"null"
]
} ,
"itemId" : {
"type" : "string"
} ,
"reason" : {
"description" : "Optional explanatory reason (e.g. request for extra write access)." ,
"type" : [
"string" ,
"null"
]
} ,
"threadId" : {
"type" : "string"
} ,
"turnId" : {
"type" : "string"
}
} ,
"required" : [
"itemId" ,
"threadId" ,
"turnId"
] ,
"type" : "object"
} ,
2026-03-05 16:21:45 -08:00
"MacOsAutomationPermission" : {
"oneOf" : [
feat: add experimental additionalPermissions to v2 command execution approval requests (#12737)
This adds additionalPermissions to the app-server v2
item/commandExecution/requestApproval payload as an experimental field.
The field is now exposed on CommandExecutionRequestApprovalParams and is
populated from the existing core approval event when a command requests
additional sandbox permissions.
This PR also contains changes to make server requests to support
experiment API.
A real app server test client test:
sample payload with experimental flag off:
```
{
< "id": 0,
< "method": "item/commandExecution/requestApproval",
< "params": {
< "command": "/bin/zsh -lc 'mkdir -p ~/some/test && touch ~/some/test/file'",
< "commandActions": [
< {
< "command": "mkdir -p '~/some/test'",
< "type": "unknown"
< },
< {
< "command": "touch '~/some/test/file'",
< "type": "unknown"
< }
< ],
< "cwd": "/Users/celia/code/codex/codex-rs",
< "itemId": "call_QLp0LWkQ1XkU6VW9T2vUZFWB",
< "proposedExecpolicyAmendment": [
< "mkdir",
< "-p",
< "~/some/test"
< ],
< "reason": "Do you want to allow creating ~/some/test/file outside the workspace?",
< "threadId": "019c9309-e209-7d82-a01b-dcf9556a354d",
< "turnId": "019c9309-e27a-7f33-834f-6011e795c2d6"
< }
< }
```
with experimental flag on:
```
< {
< "id": 0,
< "method": "item/commandExecution/requestApproval",
< "params": {
< "additionalPermissions": {
< "fileSystem": null,
< "macos": null,
< "network": true
< },
< "command": "/bin/zsh -lc 'install -D /dev/null ~/some/test/file'",
< "commandActions": [
< {
< "command": "install -D /dev/null '~/some/test/file'",
< "type": "unknown"
< }
< ],
< "cwd": "/Users/celia/code/codex/codex-rs",
< "itemId": "call_K3U4b3dRbj3eMCqslmncbGsq",
< "proposedExecpolicyAmendment": [
< "install",
< "-D"
< ],
< "reason": "Do you want to allow creating the file at ~/some/test/file outside the workspace sandbox?",
< "threadId": "019c9303-3a8e-76e1-81bf-d67ac446d892",
< "turnId": "019c9303-3af1-7143-88a1-73132f771234"
< }
< }
```
2026-02-24 21:16:35 -08:00
{
2026-03-05 16:21:45 -08:00
"enum" : [
"none" ,
"all"
] ,
"type" : "string"
feat: add experimental additionalPermissions to v2 command execution approval requests (#12737)
This adds additionalPermissions to the app-server v2
item/commandExecution/requestApproval payload as an experimental field.
The field is now exposed on CommandExecutionRequestApprovalParams and is
populated from the existing core approval event when a command requests
additional sandbox permissions.
This PR also contains changes to make server requests to support
experiment API.
A real app server test client test:
sample payload with experimental flag off:
```
{
< "id": 0,
< "method": "item/commandExecution/requestApproval",
< "params": {
< "command": "/bin/zsh -lc 'mkdir -p ~/some/test && touch ~/some/test/file'",
< "commandActions": [
< {
< "command": "mkdir -p '~/some/test'",
< "type": "unknown"
< },
< {
< "command": "touch '~/some/test/file'",
< "type": "unknown"
< }
< ],
< "cwd": "/Users/celia/code/codex/codex-rs",
< "itemId": "call_QLp0LWkQ1XkU6VW9T2vUZFWB",
< "proposedExecpolicyAmendment": [
< "mkdir",
< "-p",
< "~/some/test"
< ],
< "reason": "Do you want to allow creating ~/some/test/file outside the workspace?",
< "threadId": "019c9309-e209-7d82-a01b-dcf9556a354d",
< "turnId": "019c9309-e27a-7f33-834f-6011e795c2d6"
< }
< }
```
with experimental flag on:
```
< {
< "id": 0,
< "method": "item/commandExecution/requestApproval",
< "params": {
< "additionalPermissions": {
< "fileSystem": null,
< "macos": null,
< "network": true
< },
< "command": "/bin/zsh -lc 'install -D /dev/null ~/some/test/file'",
< "commandActions": [
< {
< "command": "install -D /dev/null '~/some/test/file'",
< "type": "unknown"
< }
< ],
< "cwd": "/Users/celia/code/codex/codex-rs",
< "itemId": "call_K3U4b3dRbj3eMCqslmncbGsq",
< "proposedExecpolicyAmendment": [
< "install",
< "-D"
< ],
< "reason": "Do you want to allow creating the file at ~/some/test/file outside the workspace sandbox?",
< "threadId": "019c9303-3a8e-76e1-81bf-d67ac446d892",
< "turnId": "019c9303-3af1-7143-88a1-73132f771234"
< }
< }
```
2026-02-24 21:16:35 -08:00
} ,
{
2026-03-05 16:21:45 -08:00
"additionalProperties" : false ,
"properties" : {
"bundle_ids" : {
"items" : {
"type" : "string"
} ,
"type" : "array"
}
feat: add experimental additionalPermissions to v2 command execution approval requests (#12737)
This adds additionalPermissions to the app-server v2
item/commandExecution/requestApproval payload as an experimental field.
The field is now exposed on CommandExecutionRequestApprovalParams and is
populated from the existing core approval event when a command requests
additional sandbox permissions.
This PR also contains changes to make server requests to support
experiment API.
A real app server test client test:
sample payload with experimental flag off:
```
{
< "id": 0,
< "method": "item/commandExecution/requestApproval",
< "params": {
< "command": "/bin/zsh -lc 'mkdir -p ~/some/test && touch ~/some/test/file'",
< "commandActions": [
< {
< "command": "mkdir -p '~/some/test'",
< "type": "unknown"
< },
< {
< "command": "touch '~/some/test/file'",
< "type": "unknown"
< }
< ],
< "cwd": "/Users/celia/code/codex/codex-rs",
< "itemId": "call_QLp0LWkQ1XkU6VW9T2vUZFWB",
< "proposedExecpolicyAmendment": [
< "mkdir",
< "-p",
< "~/some/test"
< ],
< "reason": "Do you want to allow creating ~/some/test/file outside the workspace?",
< "threadId": "019c9309-e209-7d82-a01b-dcf9556a354d",
< "turnId": "019c9309-e27a-7f33-834f-6011e795c2d6"
< }
< }
```
with experimental flag on:
```
< {
< "id": 0,
< "method": "item/commandExecution/requestApproval",
< "params": {
< "additionalPermissions": {
< "fileSystem": null,
< "macos": null,
< "network": true
< },
< "command": "/bin/zsh -lc 'install -D /dev/null ~/some/test/file'",
< "commandActions": [
< {
< "command": "install -D /dev/null '~/some/test/file'",
< "type": "unknown"
< }
< ],
< "cwd": "/Users/celia/code/codex/codex-rs",
< "itemId": "call_K3U4b3dRbj3eMCqslmncbGsq",
< "proposedExecpolicyAmendment": [
< "install",
< "-D"
< ],
< "reason": "Do you want to allow creating the file at ~/some/test/file outside the workspace sandbox?",
< "threadId": "019c9303-3a8e-76e1-81bf-d67ac446d892",
< "turnId": "019c9303-3af1-7143-88a1-73132f771234"
< }
< }
```
2026-02-24 21:16:35 -08:00
} ,
2026-03-05 16:21:45 -08:00
"required" : [
"bundle_ids"
] ,
"title" : "BundleIdsMacOsAutomationPermission" ,
"type" : "object"
feat: add experimental additionalPermissions to v2 command execution approval requests (#12737)
This adds additionalPermissions to the app-server v2
item/commandExecution/requestApproval payload as an experimental field.
The field is now exposed on CommandExecutionRequestApprovalParams and is
populated from the existing core approval event when a command requests
additional sandbox permissions.
This PR also contains changes to make server requests to support
experiment API.
A real app server test client test:
sample payload with experimental flag off:
```
{
< "id": 0,
< "method": "item/commandExecution/requestApproval",
< "params": {
< "command": "/bin/zsh -lc 'mkdir -p ~/some/test && touch ~/some/test/file'",
< "commandActions": [
< {
< "command": "mkdir -p '~/some/test'",
< "type": "unknown"
< },
< {
< "command": "touch '~/some/test/file'",
< "type": "unknown"
< }
< ],
< "cwd": "/Users/celia/code/codex/codex-rs",
< "itemId": "call_QLp0LWkQ1XkU6VW9T2vUZFWB",
< "proposedExecpolicyAmendment": [
< "mkdir",
< "-p",
< "~/some/test"
< ],
< "reason": "Do you want to allow creating ~/some/test/file outside the workspace?",
< "threadId": "019c9309-e209-7d82-a01b-dcf9556a354d",
< "turnId": "019c9309-e27a-7f33-834f-6011e795c2d6"
< }
< }
```
with experimental flag on:
```
< {
< "id": 0,
< "method": "item/commandExecution/requestApproval",
< "params": {
< "additionalPermissions": {
< "fileSystem": null,
< "macos": null,
< "network": true
< },
< "command": "/bin/zsh -lc 'install -D /dev/null ~/some/test/file'",
< "commandActions": [
< {
< "command": "install -D /dev/null '~/some/test/file'",
< "type": "unknown"
< }
< ],
< "cwd": "/Users/celia/code/codex/codex-rs",
< "itemId": "call_K3U4b3dRbj3eMCqslmncbGsq",
< "proposedExecpolicyAmendment": [
< "install",
< "-D"
< ],
< "reason": "Do you want to allow creating the file at ~/some/test/file outside the workspace sandbox?",
< "threadId": "019c9303-3a8e-76e1-81bf-d67ac446d892",
< "turnId": "019c9303-3af1-7143-88a1-73132f771234"
< }
< }
```
2026-02-24 21:16:35 -08:00
}
]
} ,
2026-03-10 16:34:47 -07:00
"MacOsContactsPermission" : {
"enum" : [
"none" ,
"read_only" ,
"read_write"
] ,
"type" : "string"
} ,
2026-03-05 16:21:45 -08:00
"MacOsPreferencesPermission" : {
"enum" : [
"none" ,
"read_only" ,
"read_write"
] ,
"type" : "string"
feat: add experimental additionalPermissions to v2 command execution approval requests (#12737)
This adds additionalPermissions to the app-server v2
item/commandExecution/requestApproval payload as an experimental field.
The field is now exposed on CommandExecutionRequestApprovalParams and is
populated from the existing core approval event when a command requests
additional sandbox permissions.
This PR also contains changes to make server requests to support
experiment API.
A real app server test client test:
sample payload with experimental flag off:
```
{
< "id": 0,
< "method": "item/commandExecution/requestApproval",
< "params": {
< "command": "/bin/zsh -lc 'mkdir -p ~/some/test && touch ~/some/test/file'",
< "commandActions": [
< {
< "command": "mkdir -p '~/some/test'",
< "type": "unknown"
< },
< {
< "command": "touch '~/some/test/file'",
< "type": "unknown"
< }
< ],
< "cwd": "/Users/celia/code/codex/codex-rs",
< "itemId": "call_QLp0LWkQ1XkU6VW9T2vUZFWB",
< "proposedExecpolicyAmendment": [
< "mkdir",
< "-p",
< "~/some/test"
< ],
< "reason": "Do you want to allow creating ~/some/test/file outside the workspace?",
< "threadId": "019c9309-e209-7d82-a01b-dcf9556a354d",
< "turnId": "019c9309-e27a-7f33-834f-6011e795c2d6"
< }
< }
```
with experimental flag on:
```
< {
< "id": 0,
< "method": "item/commandExecution/requestApproval",
< "params": {
< "additionalPermissions": {
< "fileSystem": null,
< "macos": null,
< "network": true
< },
< "command": "/bin/zsh -lc 'install -D /dev/null ~/some/test/file'",
< "commandActions": [
< {
< "command": "install -D /dev/null '~/some/test/file'",
< "type": "unknown"
< }
< ],
< "cwd": "/Users/celia/code/codex/codex-rs",
< "itemId": "call_K3U4b3dRbj3eMCqslmncbGsq",
< "proposedExecpolicyAmendment": [
< "install",
< "-D"
< ],
< "reason": "Do you want to allow creating the file at ~/some/test/file outside the workspace sandbox?",
< "threadId": "019c9303-3a8e-76e1-81bf-d67ac446d892",
< "turnId": "019c9303-3af1-7143-88a1-73132f771234"
< }
< }
```
2026-02-24 21:16:35 -08:00
} ,
2026-03-06 01:50:26 -08:00
"McpElicitationArrayType" : {
"enum" : [
"array"
] ,
"type" : "string"
} ,
"McpElicitationBooleanSchema" : {
"additionalProperties" : false ,
"properties" : {
"default" : {
"type" : [
"boolean" ,
"null"
]
} ,
"description" : {
"type" : [
"string" ,
"null"
]
} ,
"title" : {
"type" : [
"string" ,
"null"
]
} ,
"type" : {
"$ref" : "#/definitions/McpElicitationBooleanType"
}
} ,
"required" : [
"type"
] ,
"type" : "object"
} ,
"McpElicitationBooleanType" : {
"enum" : [
"boolean"
] ,
"type" : "string"
} ,
"McpElicitationConstOption" : {
"additionalProperties" : false ,
"properties" : {
"const" : {
"type" : "string"
} ,
"title" : {
"type" : "string"
}
} ,
"required" : [
"const" ,
"title"
] ,
"type" : "object"
} ,
"McpElicitationEnumSchema" : {
"anyOf" : [
{
"$ref" : "#/definitions/McpElicitationSingleSelectEnumSchema"
} ,
{
"$ref" : "#/definitions/McpElicitationMultiSelectEnumSchema"
} ,
{
"$ref" : "#/definitions/McpElicitationLegacyTitledEnumSchema"
}
]
} ,
"McpElicitationLegacyTitledEnumSchema" : {
"additionalProperties" : false ,
"properties" : {
"default" : {
"type" : [
"string" ,
"null"
]
} ,
"description" : {
"type" : [
"string" ,
"null"
]
} ,
"enum" : {
"items" : {
"type" : "string"
} ,
"type" : "array"
} ,
"enumNames" : {
"items" : {
"type" : "string"
} ,
"type" : [
"array" ,
"null"
]
} ,
"title" : {
"type" : [
"string" ,
"null"
]
} ,
"type" : {
"$ref" : "#/definitions/McpElicitationStringType"
}
} ,
"required" : [
"enum" ,
"type"
] ,
"type" : "object"
} ,
"McpElicitationMultiSelectEnumSchema" : {
"anyOf" : [
{
"$ref" : "#/definitions/McpElicitationUntitledMultiSelectEnumSchema"
} ,
{
"$ref" : "#/definitions/McpElicitationTitledMultiSelectEnumSchema"
}
]
} ,
"McpElicitationNumberSchema" : {
"additionalProperties" : false ,
"properties" : {
"default" : {
"format" : "double" ,
"type" : [
"number" ,
"null"
]
} ,
"description" : {
"type" : [
"string" ,
"null"
]
} ,
"maximum" : {
"format" : "double" ,
"type" : [
"number" ,
"null"
]
} ,
"minimum" : {
"format" : "double" ,
"type" : [
"number" ,
"null"
]
} ,
"title" : {
"type" : [
"string" ,
"null"
]
} ,
"type" : {
"$ref" : "#/definitions/McpElicitationNumberType"
}
} ,
"required" : [
"type"
] ,
"type" : "object"
} ,
"McpElicitationNumberType" : {
"enum" : [
"number" ,
"integer"
] ,
"type" : "string"
} ,
"McpElicitationObjectType" : {
"enum" : [
"object"
] ,
"type" : "string"
} ,
"McpElicitationPrimitiveSchema" : {
"anyOf" : [
{
"$ref" : "#/definitions/McpElicitationEnumSchema"
} ,
{
"$ref" : "#/definitions/McpElicitationStringSchema"
} ,
{
"$ref" : "#/definitions/McpElicitationNumberSchema"
} ,
{
"$ref" : "#/definitions/McpElicitationBooleanSchema"
}
]
} ,
"McpElicitationSchema" : {
"additionalProperties" : false ,
"description" : "Typed form schema for MCP `elicitation/create` requests.\n\nThis matches the `requestedSchema` shape from the MCP 2025-11-25 `ElicitRequestFormParams` schema." ,
"properties" : {
"$schema" : {
"type" : [
"string" ,
"null"
]
} ,
"properties" : {
"additionalProperties" : {
"$ref" : "#/definitions/McpElicitationPrimitiveSchema"
} ,
"type" : "object"
} ,
"required" : {
"items" : {
"type" : "string"
} ,
"type" : [
"array" ,
"null"
]
} ,
"type" : {
"$ref" : "#/definitions/McpElicitationObjectType"
}
} ,
"required" : [
"properties" ,
"type"
] ,
"type" : "object"
} ,
"McpElicitationSingleSelectEnumSchema" : {
"anyOf" : [
{
"$ref" : "#/definitions/McpElicitationUntitledSingleSelectEnumSchema"
} ,
{
"$ref" : "#/definitions/McpElicitationTitledSingleSelectEnumSchema"
}
]
} ,
"McpElicitationStringFormat" : {
"enum" : [
"email" ,
"uri" ,
"date" ,
"date-time"
] ,
"type" : "string"
} ,
"McpElicitationStringSchema" : {
"additionalProperties" : false ,
"properties" : {
"default" : {
"type" : [
"string" ,
"null"
]
} ,
"description" : {
"type" : [
"string" ,
"null"
]
} ,
"format" : {
"anyOf" : [
{
"$ref" : "#/definitions/McpElicitationStringFormat"
} ,
{
"type" : "null"
}
]
} ,
"maxLength" : {
"format" : "uint32" ,
"minimum" : 0.0 ,
"type" : [
"integer" ,
"null"
]
} ,
"minLength" : {
"format" : "uint32" ,
"minimum" : 0.0 ,
"type" : [
"integer" ,
"null"
]
} ,
"title" : {
"type" : [
"string" ,
"null"
]
} ,
"type" : {
"$ref" : "#/definitions/McpElicitationStringType"
}
} ,
"required" : [
"type"
] ,
"type" : "object"
} ,
"McpElicitationStringType" : {
"enum" : [
"string"
] ,
"type" : "string"
} ,
"McpElicitationTitledEnumItems" : {
"additionalProperties" : false ,
"properties" : {
"anyOf" : {
"items" : {
"$ref" : "#/definitions/McpElicitationConstOption"
} ,
"type" : "array"
}
} ,
"required" : [
"anyOf"
] ,
"type" : "object"
} ,
"McpElicitationTitledMultiSelectEnumSchema" : {
"additionalProperties" : false ,
"properties" : {
"default" : {
"items" : {
"type" : "string"
} ,
"type" : [
"array" ,
"null"
]
} ,
"description" : {
"type" : [
"string" ,
"null"
]
} ,
"items" : {
"$ref" : "#/definitions/McpElicitationTitledEnumItems"
} ,
"maxItems" : {
"format" : "uint64" ,
"minimum" : 0.0 ,
"type" : [
"integer" ,
"null"
]
} ,
"minItems" : {
"format" : "uint64" ,
"minimum" : 0.0 ,
"type" : [
"integer" ,
"null"
]
} ,
"title" : {
"type" : [
"string" ,
"null"
]
} ,
"type" : {
"$ref" : "#/definitions/McpElicitationArrayType"
}
} ,
"required" : [
"items" ,
"type"
] ,
"type" : "object"
} ,
"McpElicitationTitledSingleSelectEnumSchema" : {
"additionalProperties" : false ,
"properties" : {
"default" : {
"type" : [
"string" ,
"null"
]
} ,
"description" : {
"type" : [
"string" ,
"null"
]
} ,
"oneOf" : {
"items" : {
"$ref" : "#/definitions/McpElicitationConstOption"
} ,
"type" : "array"
} ,
"title" : {
"type" : [
"string" ,
"null"
]
} ,
"type" : {
"$ref" : "#/definitions/McpElicitationStringType"
}
} ,
"required" : [
"oneOf" ,
"type"
] ,
"type" : "object"
} ,
"McpElicitationUntitledEnumItems" : {
"additionalProperties" : false ,
"properties" : {
"enum" : {
"items" : {
"type" : "string"
} ,
"type" : "array"
} ,
"type" : {
"$ref" : "#/definitions/McpElicitationStringType"
}
} ,
"required" : [
"enum" ,
"type"
] ,
"type" : "object"
} ,
"McpElicitationUntitledMultiSelectEnumSchema" : {
"additionalProperties" : false ,
"properties" : {
"default" : {
"items" : {
"type" : "string"
} ,
"type" : [
"array" ,
"null"
]
} ,
"description" : {
"type" : [
"string" ,
"null"
]
} ,
"items" : {
"$ref" : "#/definitions/McpElicitationUntitledEnumItems"
} ,
"maxItems" : {
"format" : "uint64" ,
"minimum" : 0.0 ,
"type" : [
"integer" ,
"null"
]
} ,
"minItems" : {
"format" : "uint64" ,
"minimum" : 0.0 ,
"type" : [
"integer" ,
"null"
]
} ,
"title" : {
"type" : [
"string" ,
"null"
]
} ,
"type" : {
"$ref" : "#/definitions/McpElicitationArrayType"
}
} ,
"required" : [
"items" ,
"type"
] ,
"type" : "object"
} ,
"McpElicitationUntitledSingleSelectEnumSchema" : {
"additionalProperties" : false ,
"properties" : {
"default" : {
"type" : [
"string" ,
"null"
]
} ,
"description" : {
"type" : [
"string" ,
"null"
]
} ,
"enum" : {
"items" : {
"type" : "string"
} ,
"type" : "array"
} ,
"title" : {
"type" : [
"string" ,
"null"
]
} ,
"type" : {
"$ref" : "#/definitions/McpElicitationStringType"
}
} ,
"required" : [
"enum" ,
"type"
] ,
"type" : "object"
} ,
feat(app-server): support mcp elicitations in v2 api (#13425)
This adds a first-class server request for MCP server elicitations:
`mcpServer/elicitation/request`.
Until now, MCP elicitation requests only showed up as a raw
`codex/event/elicitation_request` event from core. That made it hard for
v2 clients to handle elicitations using the same request/response flow
as other server-driven interactions (like shell and `apply_patch`
tools).
This also updates the underlying MCP elicitation request handling in
core to pass through the full MCP request (including URL and form data)
so we can expose it properly in app-server.
### Why not `item/mcpToolCall/elicitationRequest`?
This is because MCP elicitations are related to MCP servers first, and
only optionally to a specific MCP tool call.
In the MCP protocol, elicitation is a server-to-client capability: the
server sends `elicitation/create`, and the client replies with an
elicitation result. RMCP models it that way as well.
In practice an elicitation is often triggered by an MCP tool call, but
not always.
### What changed
- add `mcpServer/elicitation/request` to the v2 app-server API
- translate core `codex/event/elicitation_request` events into the new
v2 server request
- map client responses back into `Op::ResolveElicitation` so the MCP
server can continue
- update app-server docs and generated protocol schema
- add an end-to-end app-server test that covers the full round trip
through a real RMCP elicitation flow
- The new test exercises a realistic case where an MCP tool call
triggers an elicitation, the app-server emits
mcpServer/elicitation/request, the client accepts it, and the tool call
resumes and completes successfully.
### app-server API flow
- Client starts a thread with `thread/start`.
- Client starts a turn with `turn/start`.
- App-server sends `item/started` for the `mcpToolCall`.
- While that tool call is in progress, app-server sends
`mcpServer/elicitation/request`.
- Client responds to that request with `{ action: "accept" | "decline" |
"cancel" }`.
- App-server sends `serverRequest/resolved`.
- App-server sends `item/completed` for the mcpToolCall.
- App-server sends `turn/completed`.
- If the turn is interrupted while the elicitation is pending,
app-server still sends `serverRequest/resolved` before the turn
finishes.
2026-03-05 07:20:20 -08:00
"McpServerElicitationRequestParams" : {
"oneOf" : [
{
"properties" : {
2026-03-06 01:50:26 -08:00
"_meta" : true ,
feat(app-server): support mcp elicitations in v2 api (#13425)
This adds a first-class server request for MCP server elicitations:
`mcpServer/elicitation/request`.
Until now, MCP elicitation requests only showed up as a raw
`codex/event/elicitation_request` event from core. That made it hard for
v2 clients to handle elicitations using the same request/response flow
as other server-driven interactions (like shell and `apply_patch`
tools).
This also updates the underlying MCP elicitation request handling in
core to pass through the full MCP request (including URL and form data)
so we can expose it properly in app-server.
### Why not `item/mcpToolCall/elicitationRequest`?
This is because MCP elicitations are related to MCP servers first, and
only optionally to a specific MCP tool call.
In the MCP protocol, elicitation is a server-to-client capability: the
server sends `elicitation/create`, and the client replies with an
elicitation result. RMCP models it that way as well.
In practice an elicitation is often triggered by an MCP tool call, but
not always.
### What changed
- add `mcpServer/elicitation/request` to the v2 app-server API
- translate core `codex/event/elicitation_request` events into the new
v2 server request
- map client responses back into `Op::ResolveElicitation` so the MCP
server can continue
- update app-server docs and generated protocol schema
- add an end-to-end app-server test that covers the full round trip
through a real RMCP elicitation flow
- The new test exercises a realistic case where an MCP tool call
triggers an elicitation, the app-server emits
mcpServer/elicitation/request, the client accepts it, and the tool call
resumes and completes successfully.
### app-server API flow
- Client starts a thread with `thread/start`.
- Client starts a turn with `turn/start`.
- App-server sends `item/started` for the `mcpToolCall`.
- While that tool call is in progress, app-server sends
`mcpServer/elicitation/request`.
- Client responds to that request with `{ action: "accept" | "decline" |
"cancel" }`.
- App-server sends `serverRequest/resolved`.
- App-server sends `item/completed` for the mcpToolCall.
- App-server sends `turn/completed`.
- If the turn is interrupted while the elicitation is pending,
app-server still sends `serverRequest/resolved` before the turn
finishes.
2026-03-05 07:20:20 -08:00
"message" : {
"type" : "string"
} ,
"mode" : {
"enum" : [
"form"
] ,
"type" : "string"
} ,
2026-03-06 01:50:26 -08:00
"requestedSchema" : {
"$ref" : "#/definitions/McpElicitationSchema"
}
feat(app-server): support mcp elicitations in v2 api (#13425)
This adds a first-class server request for MCP server elicitations:
`mcpServer/elicitation/request`.
Until now, MCP elicitation requests only showed up as a raw
`codex/event/elicitation_request` event from core. That made it hard for
v2 clients to handle elicitations using the same request/response flow
as other server-driven interactions (like shell and `apply_patch`
tools).
This also updates the underlying MCP elicitation request handling in
core to pass through the full MCP request (including URL and form data)
so we can expose it properly in app-server.
### Why not `item/mcpToolCall/elicitationRequest`?
This is because MCP elicitations are related to MCP servers first, and
only optionally to a specific MCP tool call.
In the MCP protocol, elicitation is a server-to-client capability: the
server sends `elicitation/create`, and the client replies with an
elicitation result. RMCP models it that way as well.
In practice an elicitation is often triggered by an MCP tool call, but
not always.
### What changed
- add `mcpServer/elicitation/request` to the v2 app-server API
- translate core `codex/event/elicitation_request` events into the new
v2 server request
- map client responses back into `Op::ResolveElicitation` so the MCP
server can continue
- update app-server docs and generated protocol schema
- add an end-to-end app-server test that covers the full round trip
through a real RMCP elicitation flow
- The new test exercises a realistic case where an MCP tool call
triggers an elicitation, the app-server emits
mcpServer/elicitation/request, the client accepts it, and the tool call
resumes and completes successfully.
### app-server API flow
- Client starts a thread with `thread/start`.
- Client starts a turn with `turn/start`.
- App-server sends `item/started` for the `mcpToolCall`.
- While that tool call is in progress, app-server sends
`mcpServer/elicitation/request`.
- Client responds to that request with `{ action: "accept" | "decline" |
"cancel" }`.
- App-server sends `serverRequest/resolved`.
- App-server sends `item/completed` for the mcpToolCall.
- App-server sends `turn/completed`.
- If the turn is interrupted while the elicitation is pending,
app-server still sends `serverRequest/resolved` before the turn
finishes.
2026-03-05 07:20:20 -08:00
} ,
"required" : [
"message" ,
"mode" ,
"requestedSchema"
] ,
"type" : "object"
} ,
{
"properties" : {
2026-03-06 01:50:26 -08:00
"_meta" : true ,
feat(app-server): support mcp elicitations in v2 api (#13425)
This adds a first-class server request for MCP server elicitations:
`mcpServer/elicitation/request`.
Until now, MCP elicitation requests only showed up as a raw
`codex/event/elicitation_request` event from core. That made it hard for
v2 clients to handle elicitations using the same request/response flow
as other server-driven interactions (like shell and `apply_patch`
tools).
This also updates the underlying MCP elicitation request handling in
core to pass through the full MCP request (including URL and form data)
so we can expose it properly in app-server.
### Why not `item/mcpToolCall/elicitationRequest`?
This is because MCP elicitations are related to MCP servers first, and
only optionally to a specific MCP tool call.
In the MCP protocol, elicitation is a server-to-client capability: the
server sends `elicitation/create`, and the client replies with an
elicitation result. RMCP models it that way as well.
In practice an elicitation is often triggered by an MCP tool call, but
not always.
### What changed
- add `mcpServer/elicitation/request` to the v2 app-server API
- translate core `codex/event/elicitation_request` events into the new
v2 server request
- map client responses back into `Op::ResolveElicitation` so the MCP
server can continue
- update app-server docs and generated protocol schema
- add an end-to-end app-server test that covers the full round trip
through a real RMCP elicitation flow
- The new test exercises a realistic case where an MCP tool call
triggers an elicitation, the app-server emits
mcpServer/elicitation/request, the client accepts it, and the tool call
resumes and completes successfully.
### app-server API flow
- Client starts a thread with `thread/start`.
- Client starts a turn with `turn/start`.
- App-server sends `item/started` for the `mcpToolCall`.
- While that tool call is in progress, app-server sends
`mcpServer/elicitation/request`.
- Client responds to that request with `{ action: "accept" | "decline" |
"cancel" }`.
- App-server sends `serverRequest/resolved`.
- App-server sends `item/completed` for the mcpToolCall.
- App-server sends `turn/completed`.
- If the turn is interrupted while the elicitation is pending,
app-server still sends `serverRequest/resolved` before the turn
finishes.
2026-03-05 07:20:20 -08:00
"elicitationId" : {
"type" : "string"
} ,
"message" : {
"type" : "string"
} ,
"mode" : {
"enum" : [
"url"
] ,
"type" : "string"
} ,
"url" : {
"type" : "string"
}
} ,
"required" : [
"elicitationId" ,
"message" ,
"mode" ,
"url"
] ,
"type" : "object"
}
] ,
"properties" : {
"serverName" : {
"type" : "string"
} ,
"threadId" : {
"type" : "string"
} ,
"turnId" : {
"description" : "Active Codex turn when this elicitation was observed, if app-server could correlate one.\n\nThis is nullable because MCP models elicitation as a standalone server-to-client request identified by the MCP server request id. It may be triggered during a turn, but turn context is app-server correlation rather than part of the protocol identity of the elicitation itself." ,
"type" : [
"string" ,
"null"
]
}
} ,
"required" : [
"serverName" ,
"threadId"
] ,
"type" : "object"
} ,
2026-02-20 10:39:55 -08:00
"NetworkApprovalContext" : {
"properties" : {
"host" : {
"type" : "string"
} ,
"protocol" : {
"$ref" : "#/definitions/NetworkApprovalProtocol"
}
} ,
"required" : [
"host" ,
"protocol"
] ,
"type" : "object"
} ,
"NetworkApprovalProtocol" : {
"enum" : [
"http" ,
"https" ,
"socks5Tcp" ,
"socks5Udp"
] ,
"type" : "string"
} ,
2026-02-24 23:06:19 -08:00
"NetworkPolicyAmendment" : {
"properties" : {
"action" : {
"$ref" : "#/definitions/NetworkPolicyRuleAction"
} ,
"host" : {
"type" : "string"
}
} ,
"required" : [
"action" ,
"host"
] ,
"type" : "object"
} ,
"NetworkPolicyRuleAction" : {
"enum" : [
"allow" ,
"deny"
] ,
"type" : "string"
} ,
2026-02-01 23:38:43 -08:00
"ParsedCommand" : {
"oneOf" : [
{
"properties" : {
"cmd" : {
"type" : "string"
} ,
"name" : {
"type" : "string"
} ,
"path" : {
"description" : "(Best effort) Path to the file being read by the command. When possible, this is an absolute path, though when relative, it should be resolved against the `cwd`` that will be used to run the command to derive the absolute path." ,
"type" : "string"
} ,
"type" : {
"enum" : [
"read"
] ,
"title" : "ReadParsedCommandType" ,
"type" : "string"
}
} ,
"required" : [
"cmd" ,
"name" ,
"path" ,
"type"
] ,
"title" : "ReadParsedCommand" ,
"type" : "object"
} ,
{
"properties" : {
"cmd" : {
"type" : "string"
} ,
"path" : {
"type" : [
"string" ,
"null"
]
} ,
"type" : {
"enum" : [
"list_files"
] ,
"title" : "ListFilesParsedCommandType" ,
"type" : "string"
}
} ,
"required" : [
"cmd" ,
"type"
] ,
"title" : "ListFilesParsedCommand" ,
"type" : "object"
} ,
{
"properties" : {
"cmd" : {
"type" : "string"
} ,
"path" : {
"type" : [
"string" ,
"null"
]
} ,
"query" : {
"type" : [
"string" ,
"null"
]
} ,
"type" : {
"enum" : [
"search"
] ,
"title" : "SearchParsedCommandType" ,
"type" : "string"
}
} ,
"required" : [
"cmd" ,
"type"
] ,
"title" : "SearchParsedCommand" ,
"type" : "object"
} ,
{
"properties" : {
"cmd" : {
"type" : "string"
} ,
"type" : {
"enum" : [
"unknown"
] ,
"title" : "UnknownParsedCommandType" ,
"type" : "string"
}
} ,
"required" : [
"cmd" ,
"type"
] ,
"title" : "UnknownParsedCommand" ,
"type" : "object"
}
]
} ,
2026-03-08 20:23:06 -07:00
"PermissionsRequestApprovalParams" : {
"properties" : {
"itemId" : {
"type" : "string"
} ,
"permissions" : {
2026-03-16 10:12:23 -07:00
"$ref" : "#/definitions/RequestPermissionProfile"
2026-03-08 20:23:06 -07:00
} ,
"reason" : {
"type" : [
"string" ,
"null"
]
} ,
"threadId" : {
"type" : "string"
} ,
"turnId" : {
"type" : "string"
}
} ,
"required" : [
"itemId" ,
"permissions" ,
"threadId" ,
"turnId"
] ,
"type" : "object"
} ,
2026-02-01 23:38:43 -08:00
"RequestId" : {
"anyOf" : [
{
"type" : "string"
} ,
{
"format" : "int64" ,
"type" : "integer"
}
]
} ,
2026-03-16 10:12:23 -07:00
"RequestPermissionProfile" : {
"additionalProperties" : false ,
"properties" : {
"fileSystem" : {
"anyOf" : [
{
"$ref" : "#/definitions/AdditionalFileSystemPermissions"
} ,
{
"type" : "null"
}
]
} ,
"network" : {
"anyOf" : [
{
"$ref" : "#/definitions/AdditionalNetworkPermissions"
} ,
{
"type" : "null"
}
]
}
} ,
"type" : "object"
} ,
2026-02-01 23:38:43 -08:00
"ThreadId" : {
"type" : "string"
} ,
"ToolRequestUserInputOption" : {
"description" : "EXPERIMENTAL. Defines a single selectable option for request_user_input." ,
"properties" : {
"description" : {
"type" : "string"
} ,
"label" : {
"type" : "string"
}
} ,
"required" : [
"description" ,
"label"
] ,
"type" : "object"
} ,
"ToolRequestUserInputParams" : {
"description" : "EXPERIMENTAL. Params sent with a request_user_input event." ,
"properties" : {
"itemId" : {
"type" : "string"
} ,
"questions" : {
"items" : {
"$ref" : "#/definitions/ToolRequestUserInputQuestion"
} ,
"type" : "array"
} ,
"threadId" : {
"type" : "string"
} ,
"turnId" : {
"type" : "string"
}
} ,
"required" : [
"itemId" ,
"questions" ,
"threadId" ,
"turnId"
] ,
"type" : "object"
} ,
"ToolRequestUserInputQuestion" : {
"description" : "EXPERIMENTAL. Represents one request_user_input question and its required options." ,
"properties" : {
"header" : {
"type" : "string"
} ,
"id" : {
"type" : "string"
} ,
"isOther" : {
"default" : false ,
"type" : "boolean"
} ,
"isSecret" : {
"default" : false ,
"type" : "boolean"
} ,
"options" : {
"items" : {
"$ref" : "#/definitions/ToolRequestUserInputOption"
} ,
"type" : [
"array" ,
"null"
]
} ,
"question" : {
"type" : "string"
}
} ,
"required" : [
"header" ,
"id" ,
"question"
] ,
"type" : "object"
}
} ,
"description" : "Request initiated from the server and sent to the client." ,
"oneOf" : [
{
"description" : "NEW APIs Sent when approval is requested for a specific command execution. This request is used for Turns started via turn/start." ,
"properties" : {
"id" : {
"$ref" : "#/definitions/RequestId"
} ,
"method" : {
"enum" : [
"item/commandExecution/requestApproval"
] ,
"title" : "Item/commandExecution/requestApprovalRequestMethod" ,
"type" : "string"
} ,
"params" : {
"$ref" : "#/definitions/CommandExecutionRequestApprovalParams"
}
} ,
"required" : [
"id" ,
"method" ,
"params"
] ,
"title" : "Item/commandExecution/requestApprovalRequest" ,
"type" : "object"
} ,
{
"description" : "Sent when approval is requested for a specific file change. This request is used for Turns started via turn/start." ,
"properties" : {
"id" : {
"$ref" : "#/definitions/RequestId"
} ,
"method" : {
"enum" : [
"item/fileChange/requestApproval"
] ,
"title" : "Item/fileChange/requestApprovalRequestMethod" ,
"type" : "string"
} ,
"params" : {
"$ref" : "#/definitions/FileChangeRequestApprovalParams"
}
} ,
"required" : [
"id" ,
"method" ,
"params"
] ,
"title" : "Item/fileChange/requestApprovalRequest" ,
"type" : "object"
} ,
{
"description" : "EXPERIMENTAL - Request input from the user for a tool call." ,
"properties" : {
"id" : {
"$ref" : "#/definitions/RequestId"
} ,
"method" : {
"enum" : [
"item/tool/requestUserInput"
] ,
"title" : "Item/tool/requestUserInputRequestMethod" ,
"type" : "string"
} ,
"params" : {
"$ref" : "#/definitions/ToolRequestUserInputParams"
}
} ,
"required" : [
"id" ,
"method" ,
"params"
] ,
"title" : "Item/tool/requestUserInputRequest" ,
"type" : "object"
} ,
feat(app-server): support mcp elicitations in v2 api (#13425)
This adds a first-class server request for MCP server elicitations:
`mcpServer/elicitation/request`.
Until now, MCP elicitation requests only showed up as a raw
`codex/event/elicitation_request` event from core. That made it hard for
v2 clients to handle elicitations using the same request/response flow
as other server-driven interactions (like shell and `apply_patch`
tools).
This also updates the underlying MCP elicitation request handling in
core to pass through the full MCP request (including URL and form data)
so we can expose it properly in app-server.
### Why not `item/mcpToolCall/elicitationRequest`?
This is because MCP elicitations are related to MCP servers first, and
only optionally to a specific MCP tool call.
In the MCP protocol, elicitation is a server-to-client capability: the
server sends `elicitation/create`, and the client replies with an
elicitation result. RMCP models it that way as well.
In practice an elicitation is often triggered by an MCP tool call, but
not always.
### What changed
- add `mcpServer/elicitation/request` to the v2 app-server API
- translate core `codex/event/elicitation_request` events into the new
v2 server request
- map client responses back into `Op::ResolveElicitation` so the MCP
server can continue
- update app-server docs and generated protocol schema
- add an end-to-end app-server test that covers the full round trip
through a real RMCP elicitation flow
- The new test exercises a realistic case where an MCP tool call
triggers an elicitation, the app-server emits
mcpServer/elicitation/request, the client accepts it, and the tool call
resumes and completes successfully.
### app-server API flow
- Client starts a thread with `thread/start`.
- Client starts a turn with `turn/start`.
- App-server sends `item/started` for the `mcpToolCall`.
- While that tool call is in progress, app-server sends
`mcpServer/elicitation/request`.
- Client responds to that request with `{ action: "accept" | "decline" |
"cancel" }`.
- App-server sends `serverRequest/resolved`.
- App-server sends `item/completed` for the mcpToolCall.
- App-server sends `turn/completed`.
- If the turn is interrupted while the elicitation is pending,
app-server still sends `serverRequest/resolved` before the turn
finishes.
2026-03-05 07:20:20 -08:00
{
"description" : "Request input for an MCP server elicitation." ,
"properties" : {
"id" : {
"$ref" : "#/definitions/RequestId"
} ,
"method" : {
"enum" : [
"mcpServer/elicitation/request"
] ,
"title" : "McpServer/elicitation/requestRequestMethod" ,
"type" : "string"
} ,
"params" : {
"$ref" : "#/definitions/McpServerElicitationRequestParams"
}
} ,
"required" : [
"id" ,
"method" ,
"params"
] ,
"title" : "McpServer/elicitation/requestRequest" ,
"type" : "object"
} ,
2026-03-08 20:23:06 -07:00
{
"description" : "Request approval for additional permissions from the user." ,
"properties" : {
"id" : {
"$ref" : "#/definitions/RequestId"
} ,
"method" : {
"enum" : [
"item/permissions/requestApproval"
] ,
"title" : "Item/permissions/requestApprovalRequestMethod" ,
"type" : "string"
} ,
"params" : {
"$ref" : "#/definitions/PermissionsRequestApprovalParams"
}
} ,
"required" : [
"id" ,
"method" ,
"params"
] ,
"title" : "Item/permissions/requestApprovalRequest" ,
"type" : "object"
} ,
2026-02-01 23:38:43 -08:00
{
"description" : "Execute a dynamic tool call on the client." ,
"properties" : {
"id" : {
"$ref" : "#/definitions/RequestId"
} ,
"method" : {
"enum" : [
"item/tool/call"
] ,
"title" : "Item/tool/callRequestMethod" ,
"type" : "string"
} ,
"params" : {
"$ref" : "#/definitions/DynamicToolCallParams"
}
} ,
"required" : [
"id" ,
"method" ,
"params"
] ,
"title" : "Item/tool/callRequest" ,
"type" : "object"
} ,
{
"properties" : {
"id" : {
"$ref" : "#/definitions/RequestId"
} ,
"method" : {
"enum" : [
"account/chatgptAuthTokens/refresh"
] ,
"title" : "Account/chatgptAuthTokens/refreshRequestMethod" ,
"type" : "string"
} ,
"params" : {
"$ref" : "#/definitions/ChatgptAuthTokensRefreshParams"
}
} ,
"required" : [
"id" ,
"method" ,
"params"
] ,
"title" : "Account/chatgptAuthTokens/refreshRequest" ,
"type" : "object"
} ,
{
"description" : "DEPRECATED APIs below Request to approve a patch. This request is used for Turns started via the legacy APIs (i.e. SendUserTurn, SendUserMessage)." ,
"properties" : {
"id" : {
"$ref" : "#/definitions/RequestId"
} ,
"method" : {
"enum" : [
"applyPatchApproval"
] ,
"title" : "ApplyPatchApprovalRequestMethod" ,
"type" : "string"
} ,
"params" : {
"$ref" : "#/definitions/ApplyPatchApprovalParams"
}
} ,
"required" : [
"id" ,
"method" ,
"params"
] ,
"title" : "ApplyPatchApprovalRequest" ,
"type" : "object"
} ,
{
"description" : "Request to exec a command. This request is used for Turns started via the legacy APIs (i.e. SendUserTurn, SendUserMessage)." ,
"properties" : {
"id" : {
"$ref" : "#/definitions/RequestId"
} ,
"method" : {
"enum" : [
"execCommandApproval"
] ,
"title" : "ExecCommandApprovalRequestMethod" ,
"type" : "string"
} ,
"params" : {
"$ref" : "#/definitions/ExecCommandApprovalParams"
}
} ,
"required" : [
"id" ,
"method" ,
"params"
] ,
"title" : "ExecCommandApprovalRequest" ,
"type" : "object"
}
] ,
"title" : "ServerRequest"
}