Forward model confirmation policies to actor MCP tools (#41072)

## What changed

- Add optional Browser Use and Computer Use confirmation-policy Markdown to model catalog messages.
- Send the configured documents verbatim in `openai/confirmation_policies` metadata for `node_repl` and `cua_repl` tool calls. Send an empty object when the issuing model has no policies so runtime defaults are cleared.
- Use the issuing step's model snapshot across approval waits, and omit the metadata for other MCP servers and Guardian sessions.

## Testing

- Cover policy serialization, configuration overrides, model changes, approval waits, partial or empty policies, eligible server filtering, and Guardian exclusion.

GitOrigin-RevId: 038c4c262a31fc71986e4a2a947fe9bcbd407acc
This commit is contained in:
Ankush Gupta authored and copyberry committed 2026-08-27 06:58:07 +00:00
1 parent 218a3e50ae
commit b592a0bfed
16 files changed
+434 -7

No files matched your search

+42
View File
@@ -45,7 +45,9 @@ use codex_protocol::items::McpToolCallError;
use codex_protocol::items::McpToolCallItem;
use codex_protocol::items::McpToolCallStatus;
use codex_protocol::items::TurnItem;
use codex_protocol::mcp::CONFIRMATION_POLICIES_META_KEY;
use codex_protocol::mcp::CallToolResult;
use codex_protocol::mcp::is_node_repl_backed_server;
use codex_protocol::mcp_approval_meta::APPROVAL_KIND_KEY as MCP_TOOL_APPROVAL_KIND_KEY;
use codex_protocol::mcp_approval_meta::APPROVAL_KIND_MCP_TOOL_CALL as MCP_TOOL_APPROVAL_KIND_MCP_TOOL_CALL;
use codex_protocol::mcp_approval_meta::CONNECTOR_DESCRIPTION_KEY as MCP_TOOL_APPROVAL_CONNECTOR_DESCRIPTION_KEY;
@@ -1234,9 +1236,49 @@ fn build_mcp_tool_call_request_meta(
);
}
if let Some(policies) = build_confirmation_policies_request_meta(step_context, server) {
request_meta.insert(CONFIRMATION_POLICIES_META_KEY.to_string(), policies);
}
(!request_meta.is_empty()).then_some(serde_json::Value::Object(request_meta))
}
/// Builds confirmation-policy metadata for eligible actor MCP calls.
///
/// Policies follow the issuing step's model snapshot, including across approval
/// waits. Only `node_repl`/`cua_repl` receive them; Guardian sessions are excluded.
/// Eligible calls get an empty object when no policies are configured, clearing
/// startup defaults. Text stays verbatim so runtimes own blank-value fallback.
fn build_confirmation_policies_request_meta(
step_context: &StepContext,
server: &str,
) -> Option<serde_json::Value> {
if !is_node_repl_backed_server(server)
|| crate::guardian::is_basic_session_source(&step_context.turn.session_source)
{
return None;
}
let mut policies = serde_json::Map::new();
if let Some(confirmation_policies) = step_context
.settings
.model_info
.model_messages
.as_ref()
.and_then(|messages| messages.confirmation_policies.as_ref())
{
for (name, policy) in [
("browser_use", confirmation_policies.browser_use.as_ref()),
("computer_use", confirmation_policies.computer_use.as_ref()),
] {
if let Some(policy) = policy {
policies.insert(name.to_string(), serde_json::Value::String(policy.clone()));
}
}
}
Some(serde_json::Value::Object(policies))
}
fn with_mcp_tool_call_ids_meta(
meta: Option<serde_json::Value>,
thread_id: &str,