Tasks
Neva clients support long-running tasks — an extended way to call tools asynchronously with optional TTL-based cancellation and lifecycle management.
Enabling Tasks on the Client
Use with_tasks() to enable task support:
use std::time::Duration;
use neva::prelude::*;
#[tokio::main]
async fn main() -> Result<(), Error> {
let mut client = Client::new()
.with_options(|opt| opt
.with_tasks(|t| t.with_all())
.with_default_http());
client.connect().await?;
// ...
client.disconnect().await
}
Calling a Tool as a Task
Use client.task() to obtain a task builder, then call call_tool() to execute a tool asynchronously as a managed task.
This is required when calling a tool that has task_support = "required" on the server side (see the server Tasks guide).
let result = client
.task()
.call_tool("my_long_tool", ()).await;
println!("{:?}", result);
With a TTL
Chain with_ttl() (in milliseconds) to automatically cancel the task if it exceeds the given time limit:
let ttl = 10_000; // 10 seconds
let result = client
.task()
.with_ttl(ttl)
.call_tool("endless_tool", ()).await;
If the TTL expires before the tool completes, the task is cancelled and an appropriate error is returned.
With Arguments
Pass arguments the same way as with call_tool():
let args = [("city1", "London"), ("city2", "Paris")];
let result = client
.task()
.call_tool("generate_weather_report", args).await;
Listing Active Tasks
Use list_tasks() to retrieve the current list of running or completed tasks:
let tasks = client.list_tasks(None).await?;
println!("{:?}", tasks);
Handling Sampling and Elicitation in Tasks
Task-capable tools may trigger sampling or elicitation mid-execution.
To support these interactions, register handlers using the #[sampling] and #[elicitation] macros. The framework invokes them automatically when the server-side tool calls ctx.sample() or ctx.elicit() during task execution.
#[sampling]
async fn sampling_handler(params: CreateMessageRequestParams) -> CreateMessageResult {
CreateMessageResult::assistant()
.with_model("gpt-5")
.with_content("Response text")
.end_turn()
}
#[elicitation]
async fn elicitation_handler(params: ElicitRequestParams) -> ElicitResult {
match params {
ElicitRequestParams::Url(_url) => ElicitResult::accept(),
ElicitRequestParams::Form(_form) => ElicitResult::decline(),
}
}
Learn By Example
Here you may find the full example.