Add wire types for runtime agent registration (#55398)

## What changed

Add `codex-runtime-agent-instance` with serializable registration requests and deserializable responses. Requests support OAuth, personal access tokens, and platform API keys, along with an installation ID, public key, harness metadata, and runtime role. Responses include runtime and host IDs plus ChatGPT or platform actor context.

Use `RedactedString` for credentials to keep secrets out of debug output.

## Testing

Add tests covering request serialization for all three credential types, debug redaction, response decoding for both actor types, and rejection of responses missing required fields.

GitOrigin-RevId: f33bae734fdd1402144dee407e5b868f5eef1d37
This commit is contained in:
cooper-oai
2026-10-19 22:21:46 +00:00
committed by copyberry
parent 896604a12d
commit c3bb20602d
7 changed files with 217 additions and 0 deletions
+11
View File
@@ -4574,6 +4574,17 @@ dependencies = [
"uuid",
]
[[package]]
name = "codex-runtime-agent-instance"
version = "0.0.0"
dependencies = [
"codex-utils-redacted-string",
"pretty_assertions",
"serde",
"serde_json",
"uuid",
]
[[package]]
name = "codex-sandboxing"
version = "0.0.0"
+1
View File
@@ -102,6 +102,7 @@ members = [
"rollout-trace",
"rmcp-client",
"responses-api-proxy",
"runtime-agent-instance",
"response-debug-context",
"sandboxing",
"stdio-to-uds",
@@ -0,0 +1,6 @@
load("//:defs.bzl", "codex_rust_crate")
codex_rust_crate(
name = "runtime-agent-instance",
crate_name = "codex_runtime_agent_instance",
)
@@ -0,0 +1,20 @@
[package]
name = "codex-runtime-agent-instance"
version.workspace = true
edition.workspace = true
license.workspace = true
[lib]
doctest = false
[lints]
workspace = true
[dependencies]
codex-utils-redacted-string = { workspace = true }
serde = { workspace = true, features = ["derive"] }
uuid = { workspace = true, features = ["serde"] }
[dev-dependencies]
pretty_assertions = { workspace = true }
serde_json = { workspace = true }
@@ -0,0 +1,71 @@
//! Wire types for one-call runtime registration. Credentials are inputs, not identity claims.
use codex_utils_redacted_string::RedactedString;
use serde::Deserialize;
use serde::Serialize;
use uuid::Uuid;
#[derive(Clone, Debug, Serialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum AuthenticatedActorAuthorization {
Oauth { credential: RedactedString },
PersonalAccessToken { credential: RedactedString },
PlatformApiKey { credential: RedactedString },
}
#[derive(Clone, Debug, Serialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum AgentHostAuthorization {
// An installation ID is tracking metadata, not proof of device ownership.
InstallationId { installation_id: Uuid },
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum RuntimeRole {
Orchestrator,
Executor,
OrchestratorAndExecutor,
}
#[derive(Clone, Debug, Serialize)]
pub struct RuntimeRegistrationMetadata {
#[serde(skip_serializing_if = "Option::is_none")]
pub harness: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub harness_version: Option<String>,
pub role: RuntimeRole,
}
#[derive(Clone, Debug, Serialize)]
pub struct RuntimeRegistrationRequest {
pub actor_auth: AuthenticatedActorAuthorization,
pub agent_host_auth: AgentHostAuthorization,
pub public_key: String,
pub metadata: RuntimeRegistrationMetadata,
}
#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
pub struct RuntimeRegistrationResponse {
pub runtime_agent_instance_id: String,
pub agent_host_id: String,
pub actor: ActorInfo,
}
#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum ActorInfo {
Chatgpt {
user_id: String,
account_id: String,
},
Platform {
user_id: String,
organization_id: String,
project_id: Option<String>,
},
}
#[cfg(test)]
#[path = "bootstrap_tests.rs"]
mod tests;
@@ -0,0 +1,97 @@
//! Registration wire compatibility for each supported actor entry point.
use super::*;
use pretty_assertions::assert_eq;
use serde_json::json;
#[test]
fn registration_serializes_the_supported_actor_authorizations() {
let installation_id = "00000000-0000-4000-8000-000000000001";
for (authorization, expected) in [
(
AuthenticatedActorAuthorization::Oauth {
credential: "secret".into(),
},
json!({"type": "oauth", "credential": "secret"}),
),
(
AuthenticatedActorAuthorization::PersonalAccessToken {
credential: "secret".into(),
},
json!({"type": "personal_access_token", "credential": "secret"}),
),
(
AuthenticatedActorAuthorization::PlatformApiKey {
credential: "secret".into(),
},
json!({"type": "platform_api_key", "credential": "secret"}),
),
] {
let request = RuntimeRegistrationRequest {
actor_auth: authorization,
agent_host_auth: AgentHostAuthorization::InstallationId {
installation_id: installation_id.parse().unwrap(),
},
public_key: "ssh-ed25519 public-key".into(),
metadata: RuntimeRegistrationMetadata {
harness: Some("codex".into()),
harness_version: Some("0.0.0".into()),
role: RuntimeRole::OrchestratorAndExecutor,
},
};
assert!(!format!("{request:?}").contains("secret"));
assert_eq!(
serde_json::to_value(request).unwrap(),
json!({
"actor_auth": expected,
"agent_host_auth": {"type": "installation_id", "installation_id": installation_id},
"public_key": "ssh-ed25519 public-key",
"metadata": {"harness": "codex", "harness_version": "0.0.0", "role": "orchestrator_and_executor"},
})
);
}
}
#[test]
fn registration_decodes_composite_actor_contexts() {
for (actor, expected) in [
(
json!({"kind": "chatgpt", "user_id": "user", "account_id": "account"}),
ActorInfo::Chatgpt {
user_id: "user".into(),
account_id: "account".into(),
},
),
(
json!({"kind": "platform", "user_id": "user", "organization_id": "org", "project_id": "project"}),
ActorInfo::Platform {
user_id: "user".into(),
organization_id: "org".into(),
project_id: Some("project".into()),
},
),
] {
let response: RuntimeRegistrationResponse = serde_json::from_value(json!({
"runtime_agent_instance_id": "runtime", "agent_host_id": "host", "actor": actor,
}))
.unwrap();
assert_eq!(
response,
RuntimeRegistrationResponse {
runtime_agent_instance_id: "runtime".into(),
agent_host_id: "host".into(),
actor: expected,
}
);
}
assert!(
serde_json::from_value::<RuntimeRegistrationResponse>(
json!({"runtime_agent_instance_id": "runtime"})
)
.is_err()
);
assert!(
serde_json::from_value::<ActorInfo>(json!({"kind": "platform", "user_id": "user"}))
.is_err()
);
}
@@ -0,0 +1,11 @@
//! OpenAI runtime registration types, independent of credential storage and model providers.
mod bootstrap;
pub use bootstrap::ActorInfo;
pub use bootstrap::AgentHostAuthorization;
pub use bootstrap::AuthenticatedActorAuthorization;
pub use bootstrap::RuntimeRegistrationMetadata;
pub use bootstrap::RuntimeRegistrationRequest;
pub use bootstrap::RuntimeRegistrationResponse;
pub use bootstrap::RuntimeRole;