nanocodex-agent 0.3.0

Owned OpenAI agent lifecycle for Nanocodex
Documentation
# Nanocodex Agent

The owned lifecycle for one headless `OpenAI` coding agent.

`nanocodex-agent` composes the Tower-native Responses state machine from
`nanocodex-oai-api` with the runtime from `nanocodex-tools`. A normal consumer
builds one agent, receives a cheap cloneable [`Nanocodex`] handle and an
independent [`AgentEvents`] stream, then submits ordered prompts.

## Quick start

```rust,no_run
use nanocodex_agent::{Nanocodex, OpenAi};

# async fn run() -> 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 Rust coding agent. Preserve unrelated work and run relevant tests.",
    )
    .workspace(std::env::current_dir()?)
    .build()?;

let result = agent
    .prompt("Explain the cause of the failing parser test.")
    .await?
    .await?;
println!("{}", result.final_message());
agent.shutdown().await?;
# Ok(())
# }
```

The first `await` means the private driver accepted and ordered the prompt.
[`Turn`] is both a per-turn event stream and a future for [`TurnResult`].
Awaiting the turn waits only for its result; event consumption is independent.

The private driver is the sole owner of mutable conversation, transport, tool,
and process state. Cloning [`Nanocodex`] only clones its command capability;
[`Nanocodex::spawn`] creates a clean sibling and [`Nanocodex::fork`] creates an
independent branch from committed history.

## Typed events

[`AgentEvents`] is optional and independent from turn results. Its raw
JSONL-compatible envelope remains lossless, while
[`AgentEvent::data`](nanocodex_agent::events::AgentEvent::data) provides a
normalized domain view:

```rust,no_run
use futures_util::StreamExt;
use nanocodex_agent::{
    Nanocodex, OpenAi,
    events::{AgentEventData, AssistantEvent},
};

# async fn run() -> Result<(), Box<dyn std::error::Error>> {
let openai = OpenAi::new(std::env::var("OPENAI_API_KEY")?)?;
let (agent, mut events) = Nanocodex::builder(openai)
    .instructions("Answer concisely and preserve exact identifiers.")
    .build()?;
let turn = agent.prompt("Explain the identifier req_7f3.").await?;

while let Some(event) = events.next().await {
    if let AgentEventData::Assistant(AssistantEvent::Delta(delta)) = event.data()? {
        print!("{}", delta.text);
    }
    if event.kind.is_terminal() {
        break;
    }
}
let _result = turn.await?;
agent.shutdown().await?;
# Ok(())
# }
```

## Components

- [`events`]nanocodex_agent::events contains the complete typed lifecycle
  event taxonomy.
- [`input`]nanocodex_agent::input contains prompts and multimodal user input.
- [`session`]nanocodex_agent::session contains durable session identities and
  snapshots.
- [`usage`]nanocodex_agent::usage contains token accounting and USD estimates.
- [`rollout`]nanocodex_agent::rollout records and restores Codex-compatible
  sessions.
- [`transport`]nanocodex_agent::transport exposes advanced Responses and
  Tower configuration.
- [`tools`]nanocodex_agent::tools exposes the complete tool implementation
  surface.

OpenAI API-key and managed ChatGPT credentials belong to
[`nanocodex_oai_api::auth`], independently of this lifecycle crate.