Skip to main content

nanocodex-rust-agent-framework

Build and orchestrate frontier OpenAI agents in Rust with Nanocodex's modular components for API clients, tools, and agent lifecycle management.

Jump to install

Source facts

Repository
reason-machines/codex-skills
Last source activity
July 30, 2026 at 04:34
Detected SKILL.md language
English
Stars
0
Forks
1

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
nanocodex-rust-agent-framework
description
Build and orchestrate frontier OpenAI agents in Rust with Nanocodex's modular components for API clients, tools, and agent lifecycle management.
triggers
["build an AI agent with nanocodex","create a rust openai agent","use nanocodex agent framework","implement nanocodex tools","set up nanocodex agent session","integrate openai codex in rust","nanocodex agent examples","configure nanocodex workspace"]
# Nanocodex Rust Agent Framework > Skill by [ara.so](https://ara.so) — Codex Skills collection. Nanocodex is a Rust framework for building frontier OpenAI agents with modular, composable components. It provides building blocks for agent lifecycle management, OpenAI API integration, tool execution, and observability. The framework emphasizes small, excellent components with sharp boundaries: an OpenAI client works without an agent loop, tools work without a CLI, and the agent orchestrates these pieces cleanly. ## Installation ### CLI Installation Install the Nanocodex CLI on macOS or Linux: ```sh curl -fsSL https://nanocodex.paradigm.xyz | bash ``` Switch between versions: ```sh nanocodex update # latest stable nanocodex update 0.2.0 # specific version nanocodex update --nightly # nightly build nanocodex update --pr 50 # PR artifact (requires gh CLI) nanocodex update --path ./nanocodex # local binary ``` ### Rust Library Add to your `Cargo.toml`: ```toml [dependencies] nanocodex = "0.2" # Or with observability support nanocodex = { version = "0.2", features = ["observability"] } # Or use individual components nanocodex-agent = "0.2" nanocodex-oai-api = "0.2" nanocodex-tools = "0.2" ``` ## Core Components Nanocodex is organized into distinct layers: - **`nanocodex`** - Facade with common imports and prelude - **`nanocodex-agent`** - Agent lifecycle, prompt ordering, tool loop, cancellation - **`nanocodex-oai-api`** - OpenAI WebSocket client, authentication, session management - **`nanocodex-tools`** - Tool runtime, workspace tools, MCP support - **`nanocodex-observability`** - OpenTelemetry tracing and metrics ## Basic Agent Setup ### Minimal Agent Example ```rust use nanocodex::{Nanocodex, OpenAi}; #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { let openai = OpenAi::new(std::env::var("OPENAI_API_KEY")?)?; let (agent, mut events) = Nanocodex::builder(openai) .instructions( "You are a Rust coding agent. Make focused changes, \ preserve unrelated work, and run relevant tests before finishing." ) .workspace(std::env::current_dir()?) .build()?; // Spawn event listener let event_task = tokio::spawn(async move { while let Some(event) = events.recv().await { eprintln!("event {}: {:?}", event.seq, event.kind); if event.kind.is_terminal() { break; } } }); // Send prompt and await result let result = agent .prompt("Find and fix the failing parser test.") .await? .await?; event_task.await?; println!("{}", result.final_message()); Ok(()) } ``` ### Streaming Agent Response Stream deltas as they arrive: ```rust use nanocodex::{Nanocodex, OpenAi}; use nanocodex::agent::events::{AgentEventData, AssistantEvent}; use futures_util::StreamExt; #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { let openai = OpenAi::new(std::env::var("OPENAI_API_KEY")?)?; let (agent, _events) = Nanocodex::builder(openai) .instructions("You are a helpful assistant.") .build()?; let mut turn = agent.prompt("Explain async/await in Rust").await?; while let Some(event) = turn.next().await { if let AgentEventData::Assistant(AssistantEvent::Delta(delta)) = event.data()? { print!("{}", delta.text); } } let result = turn.await?; println!("\n\nFinal: {}", result.final_message()); Ok(()) } ``` ## Agent Builder Configuration ### Workspace and Instructions ```rust use nanocodex::{Nanocodex, OpenAi}; use std::path::PathBuf; let openai = OpenAi::new(std::env::var("OPENAI_API_KEY")?)?; let (agent, events) = Nanocodex::builder(openai) .instructions("You are a Rust expert focused on performance and correctness.") .workspace(PathBuf::from("/path/to/project")) .build()?; ``` ### Custom Tools Register custom tools with the agent: ```rust use nanocodex::{Nanocodex, OpenAi}; use nanocodex::tools::{Tool, Tools}; use serde::{Deserialize, Serialize}; use async_trait::async_trait; #[derive(Debug, Deserialize)] struct FetchUrlParams { url: String, } #[derive(Debug, Serialize)] struct FetchUrlResult { content: String, status: u16, } struct FetchUrlTool; #[async_trait] impl Tool for FetchUrlTool { fn name(&self) -> &str { "fetch_url" } fn description(&self) -> &str { "Fetch content from a URL" } fn parameters_schema(&self) -> serde_json::Value { serde_json::json!({ "type": "object", "properties": { "url": { "type": "string", "description": "The URL to fetch" } }, "required": ["url"] }) } async fn execute( &self, params: serde_json::Value, ) -> Result<serde_json::Value, Box<dyn std::error::Error + Send + Sync>> { let params: FetchUrlParams = serde_json::from_value(params)?; let response = reqwest::get(&params.url).await?; let status = response.status().as_u16(); let content = response.text().await?; let result = FetchUrlResult { content, status }; Ok(serde_json::to_value(result)?) } } #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { let openai = OpenAi::new(std::env::var("OPENAI_API_KEY")?)?; let mut tools = Tools::new(); tools.register(FetchUrlTool); let (agent, _events) = Nanocodex::builder(openai) .instructions("You can fetch URLs to help users.") .tools(tools) .build()?; let result = agent .prompt("Fetch https://example.com and summarize it") .await? .await?; println!("{}", result.final_message()); Ok(()) } ``` ### Using the Tool Macro Simplify tool creation with the `#[tool]` macro: ```rust use nanocodex::tools::tool; use serde::{Deserialize, Serialize}; #[derive(Deserialize)] struct CalculateParams { expression: String, } #[derive(Serialize)] struct CalculateResult { result: f64, } #[tool( name = "calculate", description = "Evaluate a mathematical expression" )] async fn calculate(params: CalculateParams) -> Result<CalculateResult, String> { // Simple example - real implementation would parse expression Ok(CalculateResult { result: 42.0 }) } #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { let openai = nanocodex::OpenAi::new(std::env::var("OPENAI_API_KEY")?)?; let mut tools = nanocodex::tools::Tools::new(); tools.register(calculate); let (agent, _events) = nanocodex::Nanocodex::builder(openai) .tools(tools) .build()?; Ok(()) } ``` ## OpenAI API Client (Standalone) Use the OpenAI client without the full agent: ```rust use nanocodex::oai::{OpenAi, Message, MessageContent, Role}; #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { let client = OpenAi::new(std::env::var("OPENAI_API_KEY")?)?; let session = client.session().await?; let messages = vec![ Message { role: Role::User, content: MessageContent::Text("Hello, how are you?".to_string()), } ]; let mut turn = session.chat(messages).await?; while let Some(response) = turn.next().await { let response = response?; if let Some(text) = response.text() { print!("{}", text); } } Ok(()) } ``` ## Session Management ### Multi-Turn Conversations The agent automatically maintains conversation history: ```rust use nanocodex::{Nanocodex, OpenAi}; #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { let openai = OpenAi::new(std::env::var("OPENAI_API_KEY")?)?; let (agent, _events) = Nanocodex::builder(openai) .instructions("You are a helpful assistant.") .build()?; // First turn let result1 = agent .prompt("My name is Alice") .await? .await?; println!("Turn 1: {}", result1.final_message()); // Second turn - agent remembers context let result2 = agent .prompt("What's my name?") .await? .await?; println!("Turn 2: {}", result2.final_message()); Ok(()) } ``` ### Cloning Agent Handles Create cheap clones for concurrent access: ```rust let agent_clone = agent.clone(); tokio::spawn(async move { let result = agent_clone .prompt("Background task") .await? .await?; Ok::<_, Box<dyn std::error::Error>>(()) }); ``` ### Forking Sessions Create branching conversations: ```rust // Fork from current state let forked_agent = agent.fork().await?; // Fork from specific snapshot let snapshot_id = result.snapshot_id(); let branched_agent = agent.fork_from(snapshot_id).await?; // Spawn new independent session let spawned_agent = agent.spawn().await?; ``` ## CLI Usage ### Interactive TUI Mode ```sh nanocodex ``` ### One-Shot Commands ```sh nanocodex run "implement a binary search function in src/search.rs" ``` ### VM-Backed Tools Run tools in an isolated VM: ```sh # Build VM guest runtime just build-vm-guest # Run with VM backing nanocodex \ --vm .nanocodex/vm/session-rootfs.ext4 \ --vm-guest-runtime target/aarch64-unknown-linux-musl/debug/nanocodex-vm-guest \ --vm-workspace /app # One-shot with VM nanocodex run "inspect the repository" \ --vm .nanocodex/vm/session-rootfs.ext4 \ --vm-guest-runtime target/aarch64-unknown-linux-musl/debug/nanocodex-vm-guest \ --vm-workspace /app ``` ## Observability ### Enable Tracing ```rust use nanocodex::observability::{init_tracing, TracingConfig}; #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { init_tracing(TracingConfig::default())?; let openai = nanocodex::OpenAi::new(std::env::var("OPENAI_API_KEY")?)?;
View on GitHub
This SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub