Create the new `pika-managed-agent-contract` crate
Intent: Introduce a minimal crate whose sole purpose is to house the shared agent-provisioning types so they can be depended on without pulling in `pika-cloud`.
Affected files: crates/pika-managed-agent-contract/Cargo.toml, crates/pika-managed-agent-contract/src/lib.rs
Evidence
@@ -0,0 +1,8 @@
+[package]
+name = "pika-managed-agent-contract"
+version = "0.1.0"
+edition = "2024"
+
+[dependencies]
+serde = { workspace = true }
+serde_json = { workspace = true }
@@ -0,0 +1,99 @@
+use serde::{Deserialize, Serialize};
+
+#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
+#[serde(rename_all = "snake_case")]
+pub enum AgentStartupPhase {
A new crate pika-managed-agent-contract is created under crates/ with only serde and serde_json as dependencies. It contains the four types that previously lived in pika-cloud:
AgentStartupPhase — enum tracking the lifecycle of an agent boot.
IncusProvisionParams — optional Incus-specific provisioning knobs.
ManagedVmProvisionParams — thin wrapper with #[serde(deny_unknown_fields)].
AgentProvisionRequest — the top-level request struct with a convenience managed_vm_params() method.
All derive macros, serde attributes, and the impl block are carried over verbatim. Three unit tests (round_trips_incus_backend, managed_vm_params_preserve_incus_request_shape, rejects_removed_legacy_fields) are included directly in the new crate, keeping the contract self-testing.
Register the crate in the workspace
Intent: Make the new crate visible to Cargo's workspace resolver and define a workspace-level dependency so downstream crates can reference it via `{ workspace = true }`.
Affected files: Cargo.toml, Cargo.lock
Evidence
@@ -8,6 +8,7 @@ members = [
"crates/pika-forge-model",
"crates/pikaci",
"crates/pika-agent-protocol",
+ "crates/pika-managed-agent-contract",
@@ -35,6 +36,7 @@ mdk-storage-traits = { git = ...
+pika-managed-agent-contract = { path = "crates/pika-managed-agent-contract" }
@@ -6026,6 +6026,14 @@ dependencies = [
+[[package]]
+name = "pika-managed-agent-contract"
+version = "0.1.0"
+dependencies = [
+ "serde",
+ "serde_json",
+]
Cargo.toml at the workspace root is updated in two places:
- The
members array gains crates/pika-managed-agent-contract.
- A new
[workspace.dependencies] entry maps the crate name to its local path.
Cargo.lock is regenerated and now contains the new package with its two dependencies.
Remove the types and tests from `pika-cloud`
Intent: Delete the now-duplicated type definitions and their tests from the original location to establish a single source of truth.
Affected files: crates/pika-cloud/src/lib.rs
Evidence
@@ -36,60 +36,6 @@ pub enum ProviderKind {
-#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
-#[serde(rename_all = "snake_case")]
-pub enum AgentStartupPhase {
@@ -121,34 +67,6 @@ mod tests {
- #[test]
- fn agent_provision_request_round_trips_incus_backend() {
The four structs/enums (AgentStartupPhase, IncusProvisionParams, ManagedVmProvisionParams, AgentProvisionRequest), the impl AgentProvisionRequest block, and the two related tests (agent_provision_request_round_trips_incus_backend, agent_provision_request_rejects_removed_legacy_fields) are all removed from crates/pika-cloud/src/lib.rs. The remaining pika-cloud types (ProviderKind, IncusGuestRunRequest, etc.) stay in place.
Re-point `pika-server` to the new crate
Intent: The server crate needs both `pika-cloud` (for other cloud types) and the new contract crate. Add the new dependency and update the re-export.
Affected files: crates/pika-server/Cargo.toml, crates/pika-server/src/managed_runtime_contract.rs
Evidence
@@ -19,6 +19,7 @@ futures = { workspace = true }
+pika-managed-agent-contract = { workspace = true }
@@ -1,6 +1,6 @@
-pub(crate) use pika_cloud::{
+pub(crate) use pika_managed_agent_contract::{
AgentProvisionRequest, AgentStartupPhase, IncusProvisionParams, ManagedVmProvisionParams,
pika-server previously obtained the agent contract types transitively through pika-cloud. Now it declares a direct dependency on pika-managed-agent-contract and its internal managed_runtime_contract.rs re-export switches the use path from pika_cloud to pika_managed_agent_contract. The pika-cloud dependency is retained for other server-side cloud types.
Switch the CLI to the new crate
Intent: The CLI only needed `pika-cloud` for the agent contract types; replace that dependency entirely.
Affected files: cli/Cargo.toml, cli/src/main.rs
Evidence
@@ -17,7 +17,7 @@ mdk-storage-traits = { workspace = true }
-pika-cloud = { path = "../crates/pika-cloud" }
+pika-managed-agent-contract = { workspace = true }
@@ -14,7 +14,7 @@ use clap::{Args, Parser, Subcommand, ValueEnum};
-use pika_cloud::{AgentProvisionRequest, AgentStartupPhase, IncusProvisionParams};
+use pika_managed_agent_contract::{AgentProvisionRequest, AgentStartupPhase, IncusProvisionParams};
In cli/Cargo.toml the pika-cloud dependency is replaced with pika-managed-agent-contract (workspace reference). The corresponding use statement in cli/src/main.rs is updated to import AgentProvisionRequest, AgentStartupPhase, and IncusProvisionParams from the new crate. This removes the CLI's transitive dependency on everything pika-cloud pulls in.
Switch the Rust SDK to the new crate
Intent: Same rationale as the CLI — the Rust SDK only consumed the agent contract types from `pika-cloud`.
Affected files: rust/Cargo.toml, rust/src/core/agent.rs
Evidence
@@ -26,7 +26,7 @@ keyring-core = { workspace = true }
-pika-cloud = { path = "../crates/pika-cloud" }
+pika-managed-agent-contract = { workspace = true }
@@ -2,7 +2,7 @@ use std::time::Duration;
-use pika_cloud::{AgentProvisionRequest, AgentStartupPhase, IncusProvisionParams};
+use pika_managed_agent_contract::{AgentProvisionRequest, AgentStartupPhase, IncusProvisionParams};
The rust/ SDK crate mirrors the CLI change: pika-cloud is swapped for pika-managed-agent-contract in Cargo.toml, and the import in rust/src/core/agent.rs is rewritten. The SDK no longer has any dependency on pika-cloud.