# Turn

One running turn of an agent: a future of its result and a stream of its events, with steering and cancellation.

`Agent.prompt` returns a `Turn`. Await the turn for its `TurnResult`, or first read it as a `Stream` of `AgentEvent` values, for example with `futures::StreamExt`. A dropped `Turn` keeps running, so the compiler warns when a turn is not used.

```rust
use futures::StreamExt;

// 1. Start a turn and print its events as they arrive
let mut turn = agent.prompt("Summarize the README.").await?;
while let Some(event) = turn.next().await {
    eprintln!("{:?}", event.kind);
}

// 2. Read the result after the stream ends
let result = turn.result().await?;
println!("{}", result.final_message());
```

## Signature

```rust
// Await it for the result, or poll it for events
pub struct Turn;

impl Future for Turn {
    type Output = Result<TurnResult, NanocodeError>;
}

impl Stream for Turn {
    type Item = AgentEvent;
}
```

## Methods

### id

```rust
// The turn ID
pub fn id(&self) -> &str
```

Returns the ID of the turn. If the prompt has a request ID, the turn ID is usually that request ID.

```rust
// Logs the turn as it starts
let turn = agent.prompt("Run the tests.").await?;
eprintln!("turn {}", turn.id());
```

### steer

```rust
// Adds an instruction to the running turn
pub async fn steer(
    &self,
    prompt: impl Into<Prompt>) -> Result<(,
), NanocodeError>
```

Sends more input to the turn while it runs. `steer_with_id` takes an ID, and `withdraw_steer(id)` removes that input if the turn has not used it yet.

```rust
// Narrows the task while the model works
turn.steer("Only check the src directory.").await?;
```

### cancel

```rust
// Cancels this turn
pub async fn cancel(&self) -> Result<(), NanocodeError>
```

Cancels the turn. Awaiting the turn then returns `NanocodeError::TurnCancelled`.

```rust
// Cancels a turn that runs too long
turn.cancel().await?;
```

### control

```rust
// A cloneable handle for steering and cancellation
pub fn control(&self) -> TurnControl
```

Returns a `TurnControl` with `steer`, `steer_with_id`, `withdraw_steer`, and `cancel`. Another task can hold it while the `Turn` is awaited.

```rust
// Cancels from a timer while the turn is awaited
let control = turn.control();
tokio::spawn(async move {
    tokio::time::sleep(std::time::Duration::from_secs(60)).await;
    let _ = control.cancel().await;
});
let result = turn.await;
```

### result

```rust
// Drops the event stream and awaits the result
pub async fn result(self) -> Result<TurnResult, NanocodeError>
```

Awaits the result without the turn's events. `turn.await` and `turn.result().await` return the same value.

```rust
// Reads only the final message
let message = turn.result().await?.into_final_message();
```

## TurnResult

The result of a completed turn.

```rust
// Reads the parts of a result
let result = agent.prompt("Say hello.").await?.await?;
println!("{}", result.final_message());
```

### final_message

* **Type:** `&str`

The final assistant message. `into_final_message` returns it as a `String`.

```rust
// Moves the message out of the result
let text: String = result.into_final_message();
```

### usage

* **Type:** `Option<&TurnUsage>`

The token counts and estimated cost of the turn. See [`TurnUsage`](/docs/api/rust/types#turnusage).

```rust
// Prints the total tokens when the backend reports usage
if let Some(usage) = result.usage() {
    println!("{} tokens", usage.total_tokens());
}
```

### turn_id

* **Type:** `Option<&str>`

The ID of the turn that produced the result.

```rust
// Matches the result to its turn
println!("{:?}", result.turn_id());
```

### request_id

* **Type:** `Option<&str>`

The request ID of the prompt, when the prompt had one.

```rust
// Prints Some("checklist-1") for an identified prompt
println!("{:?}", result.request_id());
```

### checkpoint

* **Type:** `Option<SessionCheckpoint>`

A checkpoint at the end of this turn, when the backend records one. `try_checkpoint` returns the error instead of `None`.

```rust
// Saves a checkpoint after each turn
if let Some(checkpoint) = result.checkpoint() {
    std::fs::write("checkpoint.json", checkpoint.to_json()?)?;
}
```

## PromptRequest

The input of `Agent.prompt`: a prompt and optional delivery settings. `Prompt`, `String`, and `&str` convert into a `PromptRequest`.

```rust
use nanocode::PromptRequest;

// The same turn, from a string and from a request
agent.prompt("Run the checklist.").await?;
agent.prompt(PromptRequest::new("Run the checklist.")).await?;
```

### PromptRequest::new

* **Type:** `fn new(prompt: impl Into<Prompt>) -> PromptRequest`

Makes a request with no request ID.

```rust
use nanocode::PromptRequest;

// Wraps a prompt for further settings
let request = PromptRequest::new("Deploy the preview.");
```

### request_id

* **Type:** `impl Into<String>`

Identifies the prompt. A repeat with the same request ID and prompt recovers the turn after a crash, or returns the recorded result after it finished. The ID must not be empty.

```rust
use nanocode::PromptRequest;

// Makes the prompt safe to retry
let request =
    PromptRequest::new("Deploy the preview.").request_id("deploy-42");
```

### cancel_on_admission

* **Type:** `fn cancel_on_admission(self) -> PromptRequest`
* **Default:** off

Records the turn as cancelled when the backend admits it, without a model request.

```rust
use nanocode::PromptRequest;

// Records the request without running it
let request = PromptRequest::new("Deploy the preview.")
    .request_id("deploy-42")
    .cancel_on_admission();
```

## Errors

### NanocodeError

Awaiting a turn returns `TurnCancelled` after `cancel`, and `TurnStopped` when the agent stops first. `steer` returns `TurnNotSteerable` when the turn is not active, and `SteerQueueFull` when its steering queue is full.

```rust
use nanocode::NanocodeError;

// Treats a cancelled turn as a normal outcome
match turn.await {
    Err(NanocodeError::TurnCancelled) => eprintln!("cancelled"),
    other => println!("{}", other?.final_message()),
}
```
