diff --git a/Cargo.toml b/Cargo.toml
index 83512b9eecde558a80f20ca6b88b0d05d7058964..90b06f55d82a8ba84088a54267d0bf5d2a8bae08 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,7 @@
 [workspace]
 resolver = "2"
 members = [
+  "crates/sdk",
   "crates/examples",
   "crates/support",
   "crates/configuration",
diff --git a/crates/examples/Cargo.toml b/crates/examples/Cargo.toml
index a39fd0e23c7a9fa00f7bc41cca2fce6557d4ebda..ca65ee13c0e7f78b08b22caf9391454464cb23b9 100644
--- a/crates/examples/Cargo.toml
+++ b/crates/examples/Cargo.toml
@@ -6,12 +6,7 @@ edition = "2021"
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
 [dependencies]
-configuration = { path = "../configuration" }
-orchestrator = { path = "../orchestrator" }
-provider = { path = "../provider" }
-# TODO: we shouldn't need to pull from support, we need
-# to review the exports for neeeded types
-support = { path = "../support" }
+zombienet-sdk = { path = "../sdk" }
 tokio = { workspace = true }
 futures = { workspace = true }
 subxt = { workspace = true }
diff --git a/crates/examples/examples/simple_network_example.rs b/crates/examples/examples/simple_network_example.rs
index a8731cc2d3666ee310213d62becffff19dd9f624..5464c990d3ee86bfcd20751da31a50094adf5ae8 100644
--- a/crates/examples/examples/simple_network_example.rs
+++ b/crates/examples/examples/simple_network_example.rs
@@ -1,21 +1,13 @@
-// use std::time::Duration;
-
-use configuration::NetworkConfig;
 use futures::stream::StreamExt;
-use orchestrator::Orchestrator;
-use provider::NativeProvider;
-use support::{fs::local::LocalFileSystem, process::os::OsProcessManager};
+use zombienet_sdk::{NetworkConfig, NetworkConfigExt};
 
 #[tokio::main]
 async fn main() -> Result<(), Box<dyn std::error::Error>> {
-    let config = NetworkConfig::load_from_toml("./crates/examples/examples/0001-simple.toml")
-        .expect("errored?");
+    let network = NetworkConfig::load_from_toml("./crates/examples/examples/0001-simple.toml")
+        .expect("errored?")
+        .spawn_native()
+        .await?;
 
-    let fs = LocalFileSystem;
-    let pm = OsProcessManager;
-    let provider = NativeProvider::new(fs.clone(), pm);
-    let orchestrator = Orchestrator::new(fs, provider);
-    let network = orchestrator.spawn(config).await?;
     println!("🚀🚀🚀🚀 network deployed");
 
     let client = network
diff --git a/crates/examples/examples/small_network.rs b/crates/examples/examples/small_network.rs
index bb44ece6e7b024e663387d196237b1dd9d3bc597..6cef33dbcaab3defb73c9df399ddee6116cae8dd 100644
--- a/crates/examples/examples/small_network.rs
+++ b/crates/examples/examples/small_network.rs
@@ -1,4 +1,4 @@
-use configuration::NetworkConfigBuilder;
+use zombienet_sdk::NetworkConfigBuilder;
 
 fn main() {
     let config = NetworkConfigBuilder::new()
diff --git a/crates/examples/examples/small_network_with_default.rs b/crates/examples/examples/small_network_with_default.rs
index 663eb6c15c25810719b67f763e7f3f64288ba66d..5a32d764f1074b3ffcde43c9dc330fd13c6eb239 100644
--- a/crates/examples/examples/small_network_with_default.rs
+++ b/crates/examples/examples/small_network_with_default.rs
@@ -1,11 +1,8 @@
-use configuration::NetworkConfigBuilder;
-use orchestrator::{AddNodeOpts, Orchestrator};
-use provider::NativeProvider;
-use support::{fs::local::LocalFileSystem, process::os::OsProcessManager};
+use zombienet_sdk::{AddNodeOpts, NetworkConfigBuilder, NetworkConfigExt};
 
 #[tokio::main]
 async fn main() -> Result<(), Box<dyn std::error::Error>> {
-    let config = NetworkConfigBuilder::new()
+    let mut network = NetworkConfigBuilder::new()
         .with_relaychain(|r| {
             r.with_chain("rococo-local")
                 .with_default_command("polkadot")
@@ -18,13 +15,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
                 .with_collator(|n| n.with_name("collator").with_command("polkadot-parachain"))
         })
         .build()
-        .unwrap();
+        .unwrap()
+        .spawn_native()
+        .await?;
 
-    let fs = LocalFileSystem;
-    let pm = OsProcessManager;
-    let provider = NativeProvider::new(fs.clone(), pm);
-    let orchestrator = Orchestrator::new(fs, provider);
-    let mut network = orchestrator.spawn(config).await?;
     println!("🚀🚀🚀🚀 network deployed");
     // add  a new node
     let opts = AddNodeOpts {
@@ -36,7 +30,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
     // TODO: add check to ensure if unique
     network.add_node("new1", opts, None).await?;
 
-    // Example of some opertions that you can do
+    // Example of some operations that you can do
     // with `nodes` (e.g pause, resume, restart)
 
     // Get a ref to the node
diff --git a/crates/examples/examples/small_network_with_para.rs b/crates/examples/examples/small_network_with_para.rs
index 81ac29cac9c895bd5f8fd86d9a8a20d6b42f8599..d11b8a36cb2eeff85f364146c4e851ea25a54af4 100644
--- a/crates/examples/examples/small_network_with_para.rs
+++ b/crates/examples/examples/small_network_with_para.rs
@@ -1,13 +1,10 @@
 use std::time::Duration;
 
-use configuration::{NetworkConfigBuilder, RegistrationStrategy};
-use orchestrator::{AddNodeOpts, Orchestrator};
-use provider::NativeProvider;
-use support::{fs::local::LocalFileSystem, process::os::OsProcessManager};
+use zombienet_sdk::{AddNodeOpts, NetworkConfigBuilder, NetworkConfigExt, RegistrationStrategy};
 
 #[tokio::main]
 async fn main() -> Result<(), Box<dyn std::error::Error>> {
-    let config = NetworkConfigBuilder::new()
+    let mut network = NetworkConfigBuilder::new()
         .with_relaychain(|r| {
             r.with_chain("rococo-local")
                 .with_default_command("polkadot")
@@ -21,13 +18,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
                 .with_collator(|n| n.with_name("collator").with_command("polkadot-parachain"))
         })
         .build()
-        .unwrap();
+        .unwrap()
+        .spawn_native()
+        .await?;
 
-    let fs = LocalFileSystem;
-    let pm = OsProcessManager;
-    let provider = NativeProvider::new(fs.clone(), pm);
-    let orchestrator = Orchestrator::new(fs, provider);
-    let mut network = orchestrator.spawn(config).await?;
     println!("🚀🚀🚀🚀 network deployed");
     // add  a new node
     let opts = AddNodeOpts {
@@ -41,7 +35,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
 
     tokio::time::sleep(Duration::from_secs(2)).await;
 
-    // Example of some opertions that you can do
+    // Example of some operations that you can do
     // with `nodes` (e.g pause, resume, restart)
 
     tokio::time::sleep(Duration::from_secs(10)).await;
diff --git a/crates/orchestrator/src/lib.rs b/crates/orchestrator/src/lib.rs
index df24292bdebe574c80342c07966ff7c19cd1c067..a705b7260489a0562ce9f29cb894003b001b7b82 100644
--- a/crates/orchestrator/src/lib.rs
+++ b/crates/orchestrator/src/lib.rs
@@ -1,9 +1,9 @@
 // TODO(Javier): Remove when we implement the logic in the orchestrator to spawn with the provider.
 #![allow(dead_code)]
 
-mod errors;
+pub mod errors;
 mod generators;
-mod network;
+pub mod network;
 mod network_helper;
 mod network_spec;
 mod shared;
diff --git a/crates/orchestrator/src/network.rs b/crates/orchestrator/src/network.rs
index 27ddc232a17bac8de310e2043472aeee9d677f3e..20edbd8315f88d6740838e8124b9f0b66cd88c07 100644
--- a/crates/orchestrator/src/network.rs
+++ b/crates/orchestrator/src/network.rs
@@ -182,13 +182,22 @@ impl<T: FileSystem> Network<T> {
     // deregister and stop the collator?
     // remove_parachain()
 
-    pub fn get_node(&self, node_name: impl Into<String>) -> Result<&NetworkNode, anyhow::Error> {
-        let node_name = node_name.into();
-        if let Some(node) = self.nodes_by_name.get(&node_name) {
-            Ok(node)
-        } else {
-            Err(anyhow::anyhow!("can't find the node!"))
+    pub fn get_node(&self, name: impl Into<String>) -> Result<&NetworkNode, anyhow::Error> {
+        let name = &name.into();
+        if let Some(node) = self.nodes_by_name.get(name) {
+            return Ok(node);
         }
+
+        let list = self
+            .nodes_by_name
+            .keys()
+            .cloned()
+            .collect::<Vec<_>>()
+            .join(", ");
+
+        Err(anyhow::anyhow!(
+            "can't find node with name: {name:?}, should be one of {list}"
+        ))
     }
 
     pub fn nodes(&self) -> Vec<&NetworkNode> {
diff --git a/crates/provider/src/lib.rs b/crates/provider/src/lib.rs
index 4f48f0b0c7741de0d9fdbf1afd055cf70dd241f0..3ecb3796705efae791012068bd441d484b0d619b 100644
--- a/crates/provider/src/lib.rs
+++ b/crates/provider/src/lib.rs
@@ -86,7 +86,7 @@ pub trait ProviderNamespace {
     async fn static_setup(&self) -> Result<(), ProviderError>;
 }
 
-pub type DynNamespace = Arc<dyn ProviderNamespace>;
+pub type DynNamespace = Arc<dyn ProviderNamespace + Send + Sync>;
 
 type ExecutionResult = Result<String, (ExitStatus, String)>;
 
diff --git a/crates/sdk/Cargo.toml b/crates/sdk/Cargo.toml
new file mode 100644
index 0000000000000000000000000000000000000000..3983f3b92a6947a6be180fdbf935091c540b6511
--- /dev/null
+++ b/crates/sdk/Cargo.toml
@@ -0,0 +1,16 @@
+[package]
+name = "zombienet-sdk"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+configuration = { path = "../configuration" }
+orchestrator = { path = "../orchestrator" }
+provider = { path = "../provider" }
+support = { path = "../support" }
+async-trait = { workspace = true }
+tokio = { workspace = true }
+futures = { workspace = true }
+subxt = { workspace = true }
diff --git a/crates/sdk/src/lib.rs b/crates/sdk/src/lib.rs
new file mode 100644
index 0000000000000000000000000000000000000000..f113b2a15e47acd991b115116dd16c06b2a7c5e5
--- /dev/null
+++ b/crates/sdk/src/lib.rs
@@ -0,0 +1,31 @@
+use async_trait::async_trait;
+pub use configuration::{NetworkConfig, NetworkConfigBuilder, RegistrationStrategy};
+pub use orchestrator::{errors::OrchestratorError, network::Network, AddNodeOpts, Orchestrator};
+use provider::NativeProvider;
+use support::{fs::local::LocalFileSystem, process::os::OsProcessManager};
+
+#[async_trait]
+pub trait NetworkConfigExt {
+    /// Spawns a network using the native provider.
+    ///
+    /// # Example:
+    /// ```rust
+    /// # use zombienet_sdk::{NetworkConfig, NetworkConfigExt};
+    /// # async fn example() -> Result<(), zombienet_sdk::OrchestratorError> {
+    /// let network = NetworkConfig::load_from_toml("config.toml")?
+    ///     .spawn_native()
+    ///     .await?;
+    /// # Ok(())
+    /// # }
+    /// ```
+    async fn spawn_native(self) -> Result<Network<LocalFileSystem>, OrchestratorError>;
+}
+
+#[async_trait]
+impl NetworkConfigExt for NetworkConfig {
+    async fn spawn_native(self) -> Result<Network<LocalFileSystem>, OrchestratorError> {
+        let provider = NativeProvider::new(LocalFileSystem {}, OsProcessManager {});
+        let orchestrator = Orchestrator::new(LocalFileSystem {}, provider);
+        orchestrator.spawn(self).await
+    }
+}