> ## Documentation Index
> Fetch the complete documentation index at: https://www.edgee.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Rust SDK - Send Method

> Complete guide to the send() method in the Rust SDK.

The `send()` method is used to make non-streaming chat completion requests to the Edgee AI Gateway. It returns a `Result<SendResponse>` with the model's response.

## Arguments

| Parameter                                                                                                                      | Type                | Description                                                                                          |
| ------------------------------------------------------------------------------------------------------------------------------ | ------------------- | ---------------------------------------------------------------------------------------------------- |
| `model` <Tooltip headline="Required" tip="The field is required."><Icon icon="asterisk" size={15} color="#8924A6" /></Tooltip> | `impl Into<String>` | The model identifier to use (e.g., `"gpt-5.2"`)                                                      |
| `input`                                                                                                                        | `impl Into<Input>`  | The input for the completion. Can be a string (`&str` or `String`), `Vec<Message>`, or `InputObject` |

### Input Types

The `send()` method accepts multiple input types through the `Into<Input>` trait:

#### String Input

When `input` is a string (`&str` or `String`), it's automatically converted to a user message:

```rust theme={"dark"}
let response = client.send("gpt-5.2", "What is the capital of France?").await?;

// Equivalent to: input: InputObject::new(vec![Message::user("What is the capital of France?")])
println!("{}", response.text().unwrap_or(""));
// "The capital of France is Paris."
```

#### `Vec<Message>`

You can pass a vector of messages directly:

```rust theme={"dark"}
use edgee::Message;

let messages = vec![
    Message::system("You are a helpful assistant."),
    Message::user("What is 2+2?"),
];

let response = client.send("gpt-5.2", messages).await?;
println!("{}", response.text().unwrap_or(""));
// "2+2 equals 4."
```

#### InputObject

When `input` is an `InputObject`, you have full control over the conversation:

| Property                                                                                                                          | Type                        | Description                                                                                                                                                                     |
| --------------------------------------------------------------------------------------------------------------------------------- | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `messages` <Tooltip headline="Required" tip="The field is required."><Icon icon="asterisk" size={15} color="#8924A6" /></Tooltip> | `Vec<Message>`              | Array of conversation messages                                                                                                                                                  |
| `tools`                                                                                                                           | `Option<Vec<Tool>>`         | Array of function tools available to the model                                                                                                                                  |
| `tool_choice`                                                                                                                     | `Option<serde_json::Value>` | Controls which tool (if any) the model should call. See [Tools documentation](/sdk/rust/tools) for details                                                                      |
| `tags`                                                                                                                            | `Option<Vec<String>>`       | Optional tags to categorize and label the request for analytics and filtering. Can also be sent via the `x-edgee-tags` header (comma-separated)                                 |
| `compression_model`                                                                                                               | `Option<String>`            | Compression model for this request: `"claude"`, `"codex"`, `"opencode"`, `"cursor"`. Each model is a bundle of compression strategies. Overrides API key settings when present. |

**Example with InputObject:**

```rust theme={"dark"}
use edgee::{Message, InputObject};

let input = InputObject::new(vec![
    Message::user("What is 2+2?")
]);

let response = client.send("gpt-5.2", input).await?;
println!("{}", response.text().unwrap_or(""));
// "2+2 equals 4."
```

**Example with Tags:**

```rust theme={"dark"}
use edgee::{Message, InputObject};

let input = InputObject::new(vec![
    Message::user("Summarize this article")
]).with_tags(vec![
    "summarization".to_string(),
    "production".to_string(),
    "user-123".to_string()
]);

let response = client.send("gpt-5.2", input).await?;
```

### Message Object

Each message in the `messages` array is created using `Message` constructors:

| Constructor                            | Description                                                                            |
| -------------------------------------- | -------------------------------------------------------------------------------------- |
| `Message::system(content)`             | System instructions that set the behavior of the assistant                             |
| `Message::developer(content)`          | Instructions provided by the application developer, prioritized ahead of user messages |
| `Message::user(content)`               | Instructions provided by an end user                                                   |
| `Message::assistant(content)`          | Assistant responses (can include `tool_calls`)                                         |
| `Message::tool(tool_call_id, content)` | Results from tool/function calls                                                       |

**Message Structure:**

| Property       | Type                    | Description                                                                                                                 |
| -------------- | ----------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| `role`         | `Role`                  | The role of the message sender: `Role::System`, `Role::Developer`, `Role::User`, `Role::Assistant`, or `Role::Tool`         |
| `content`      | `Option<String>`        | The message content. Required for `System`, `User`, and `Tool` roles. Optional for `Assistant` when `tool_calls` is present |
| `tool_calls`   | `Option<Vec<ToolCall>>` | Array of tool calls made by the assistant. Only present in `Assistant` messages                                             |
| `tool_call_id` | `Option<String>`        | ID of the tool call this message is responding to. Required for `Tool` role messages                                        |

**Example - System and User Messages:**

```rust theme={"dark"}
use edgee::Message;

let messages = vec![
    Message::system("You are a helpful assistant."),
    Message::user("What is 2+2?"),
    Message::assistant("2+2 equals 4."),
    Message::user("What about 3+3?"),
];

let response = client.send("gpt-5.2", messages).await?;
println!("{}", response.text().unwrap_or(""));
// "3+3 equals 6."
```

For complete tool calling examples and best practices, see [Tools documentation](/sdk/rust/tools).

## Return Value

The `send()` method returns a `Result<SendResponse>`. On success, it contains:

### SendResponse Object

| Property      | Type                  | Description                                            |
| ------------- | --------------------- | ------------------------------------------------------ |
| `id`          | `String`              | Unique identifier for the completion                   |
| `object`      | `String`              | Object type (typically `"chat.completion"`)            |
| `created`     | `u64`                 | Unix timestamp of when the completion was created      |
| `model`       | `String`              | Model identifier used for the completion               |
| `choices`     | `Vec<Choice>`         | Array of completion choices (typically one)            |
| `usage`       | `Option<Usage>`       | Token usage information (if provided by the API)       |
| `compression` | `Option<Compression>` | Token compression metrics (if compression was applied) |

### Choice Object

Each choice in the `choices` array contains:

| Property        | Type             | Description                                                                                                             |
| --------------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `index`         | `u32`            | The index of this choice in the array                                                                                   |
| `message`       | `Message`        | The assistant's message response                                                                                        |
| `finish_reason` | `Option<String>` | Reason why the generation stopped. Possible values: `"stop"`, `"length"`, `"tool_calls"`, `"content_filter"`, or `None` |

**Example - Handling Multiple Choices:**

```rust theme={"dark"}
let response = client.send("gpt-5.2", "Give me a creative idea.").await?;

// Process all choices
for choice in &response.choices {
    println!("Choice {}: {:?}", choice.index, choice.message.content);
    println!("Finish reason: {:?}", choice.finish_reason);
}
```

### Message Object (in Response)

The `message` in each choice has:

| Property     | Type                    | Description                                                                                                 |
| ------------ | ----------------------- | ----------------------------------------------------------------------------------------------------------- |
| `role`       | `Role`                  | The role of the message (typically `Role::Assistant`)                                                       |
| `content`    | `Option<String>`        | The text content of the response. `None` when `tool_calls` is present                                       |
| `tool_calls` | `Option<Vec<ToolCall>>` | Array of tool calls requested by the model (if any). See [Tools documentation](/sdk/rust/tools) for details |

### Usage Object

Token usage information (when available):

| Property            | Type  | Description                                                   |
| ------------------- | ----- | ------------------------------------------------------------- |
| `prompt_tokens`     | `u32` | Number of tokens in the prompt (after compression if applied) |
| `completion_tokens` | `u32` | Number of tokens in the completion                            |
| `total_tokens`      | `u32` | Total tokens used (prompt + completion)                       |

**Example - Accessing Token Usage:**

```rust theme={"dark"}
let response = client.send("gpt-5.2", "Explain quantum computing briefly.").await?;

if let Some(usage) = &response.usage {
    println!("Prompt tokens: {}", usage.prompt_tokens);
    println!("Completion tokens: {}", usage.completion_tokens);
    println!("Total tokens: {}", usage.total_tokens);
}
```

### Compression Object

Token compression metrics (when compression is applied):

| Property       | Type  | Description                                                  |
| -------------- | ----- | ------------------------------------------------------------ |
| `saved_tokens` | `u32` | Number of tokens saved by compression                        |
| `cost_savings` | `u64` | Estimated cost savings in micro-units (e.g. 27000 = \$0.027) |
| `reduction`    | `f64` | Percentage reduction (e.g. 48 = 48%, may be fractional)      |
| `time_ms`      | `u32` | Time taken for compression in milliseconds                   |

**Example - Accessing Compression Metrics:**

```rust theme={"dark"}
let input = InputObject::new(vec![
    Message::user("Analyze this long document with lots of context...")
])
.with_compression_model("claude");

let response = client.send("gpt-5.2", input).await?;
println!("{}", response.text().unwrap_or(""));

if let Some(compression) = &response.compression {
    println!("Saved tokens: {}", compression.saved_tokens);
    println!("Reduction: {:.1}%", compression.reduction);
    println!("Cost savings: ${:.3}", compression.cost_savings as f64 / 1_000_000.0);
    println!("Time: {} ms", compression.time_ms);
}
```

<Note>
  The `compression` object is only present when token compression is applied to the request. Simple queries may not trigger compression.
</Note>

## Convenience Methods

The `SendResponse` struct provides convenience methods for easier access:

| Method            | Return Type              | Description                                          |
| ----------------- | ------------------------ | ---------------------------------------------------- |
| `text()`          | `Option<&str>`           | Shortcut to `choices[0].message.content.as_deref()`  |
| `message()`       | `Option<&Message>`       | Shortcut to `choices[0].message`                     |
| `finish_reason()` | `Option<&str>`           | Shortcut to `choices[0].finish_reason.as_deref()`    |
| `tool_calls()`    | `Option<&Vec<ToolCall>>` | Shortcut to `choices[0].message.tool_calls.as_ref()` |

**Example - Using Convenience Methods:**

```rust theme={"dark"}
let response = client.send("gpt-5.2", "Hello!").await?;

// Instead of: response.choices[0].message.content.as_deref()
if let Some(text) = response.text() {
    println!("{}", text);
}

// Instead of: response.choices[0].message
if let Some(message) = response.message() {
    println!("Role: {:?}", message.role);
}

// Instead of: response.choices[0].finish_reason.as_deref()
if let Some(reason) = response.finish_reason() {
    println!("Finish reason: {}", reason);
}

// Instead of: response.choices[0].message.tool_calls.as_ref()
if let Some(tool_calls) = response.tool_calls() {
    println!("Tool calls: {:?}", tool_calls);
}
```

## Error Handling

The `send()` method returns a `Result<SendResponse>`, which can contain various error types:

```rust theme={"dark"}
use edgee::{Edgee, Error};

match client.send("gpt-5.2", "Hello!").await {
    Ok(response) => {
        println!("{}", response.text().unwrap_or(""));
    }
    Err(Error::Api { status, message }) => {
        eprintln!("API error {}: {}", status, message);
    }
    Err(Error::Http(e)) => {
        eprintln!("HTTP error: {}", e);
    }
    Err(Error::Json(e)) => {
        eprintln!("JSON error: {}", e);
    }
    Err(e) => {
        eprintln!("Error: {}", e);
    }
}
```

### Common Errors

* **API errors**: `Error::Api { status, message }` - The API returned an error status
* **HTTP errors**: `Error::Http(reqwest::Error)` - Network or HTTP errors
* **JSON errors**: `Error::Json(serde_json::Error)` - JSON serialization/deserialization errors
* **Missing API key**: `Error::MissingApiKey` - API key not provided
