Skip to content

Chat Completions

Chat completions are the primary API for interacting with AI models. Both runtimes provide a unified interface that works across all 37 providers.

let client = AiClient::new("openai/gpt-4o").await?;
let response = client.chat()
.user("Hello, world!")
.execute()
.await?;
println!("{}", response.content);
client = await AiClient.create("openai/gpt-4o")
response = await client.chat() \
.user("Hello, world!") \
.execute()
print(response.content)
import { AiClient } from '@hiddenpath/ai-lib-ts';
const client = await AiClient.new('openai/gpt-4o');
const response = await client.chat().user('Hello, world!').execute();
console.log(response.content);
aiClient, _ := client.NewAiClient(ctx, "openai", nil)
response, _ := aiClient.Chat().
User("Hello, world!").
Execute(ctx)
fmt.Println(response.Content)

Set the model’s behavior:

// Rust
client.chat()
.system("You are a helpful coding assistant. Always include code examples.")
.user("Explain closures")
.execute().await?;
# Python
await client.chat() \
.system("You are a helpful coding assistant.") \
.user("Explain closures") \
.execute()
// TypeScript
await client
.chat()
.system('You are a helpful coding assistant.')
.user('Explain closures')
.execute();
// Go
aiClient.Chat().
System("You are a helpful coding assistant.").
User("Explain closures").
Execute(ctx)

Pass conversation history:

// Rust
use ai_lib_rust::{Message, MessageRole};
let messages = vec![
Message::system("You are a tutor."),
Message::user("What is recursion?"),
Message::assistant("Recursion is when a function calls itself..."),
Message::user("Can you show an example?"),
];
client.chat().messages(messages).execute().await?;
# Python
from ai_lib_python import Message
messages = [
Message.system("You are a tutor."),
Message.user("What is recursion?"),
Message.assistant("Recursion is when a function calls itself..."),
Message.user("Can you show an example?"),
]
await client.chat().messages(messages).execute()
// TypeScript
import { Message } from '@hiddenpath/ai-lib-ts';
const messages = [
Message.system('You are a tutor.'),
Message.user('What is recursion?'),
Message.assistant('Recursion is when a function calls itself...'),
Message.user('Can you show an example?'),
];
await client.chat().messages(messages).execute();
// Go
import "github.com/ailib-official/ai-protocol/pkg/ailib"
messages := []ailib.Message{
ailib.NewSystemMessage("You are a tutor."),
ailib.NewUserMessage("What is recursion?"),
ailib.NewAssistantMessage("Recursion is when a function calls itself..."),
ailib.NewUserMessage("Can you show an example?"),
}
aiClient.Chat().Messages(messages).Execute(ctx)
ParameterTypeDescription
temperaturefloatRandomness (0.0 = deterministic, 2.0 = creative)
max_tokensintMaximum response length
top_pfloatNucleus sampling (alternative to temperature)
stopstring[]Sequences that stop generation
// Rust
client.chat()
.user("Write a poem")
.temperature(0.9)
.max_tokens(200)
.top_p(0.95)
.execute().await?;
# Python
await client.chat() \
.user("Write a poem") \
.temperature(0.9) \
.max_tokens(200) \
.top_p(0.95) \
.execute()
// TypeScript
await client.chat().user('Write a poem').temperature(0.9).maxTokens(200).topP(0.95).execute();
// Go
aiClient.Chat().
User("Write a poem").
Temperature(0.9).
MaxTokens(200).
TopP(0.95).
Execute(ctx)

For real-time output, use streaming:

// Rust
let mut stream = client.chat()
.user("Tell me a story")
.stream()
.execute_stream()
.await?;
while let Some(event) = stream.next().await {
if let StreamingEvent::ContentDelta { text, .. } = event? {
print!("{text}");
std::io::stdout().flush()?;
}
}
# Python
async for event in client.chat() \
.user("Tell me a story") \
.stream():
if event.is_content_delta:
print(event.as_content_delta.text, end="", flush=True)
// TypeScript
for await (const event of client.chat().user('Tell me a story').stream()) {
if (event.isContentDelta) {
process.stdout.write(event.asContentDelta.text);
}
}
// Go
stream, _ := aiClient.Chat().User("Tell me a story").ExecuteStream(ctx)
defer stream.Close()
for stream.Next() {
event := stream.Event()
if event.Type == "content" {
fmt.Print(event.Text)
}
}

Track usage for cost management:

// Rust
let (response, stats) = client.chat()
.user("Hello")
.execute_with_stats()
.await?;
println!("Prompt tokens: {}", stats.prompt_tokens);
println!("Completion tokens: {}", stats.completion_tokens);
println!("Latency: {}ms", stats.latency_ms);
# Python
response, stats = await client.chat() \
.user("Hello") \
.execute_with_stats()
print(f"Tokens: {stats.total_tokens}")
print(f"Latency: {stats.latency_ms}ms")
// TypeScript
const { response, stats } = await client.chat().user('Hello').executeWithStats();
console.log(`Tokens: ${stats.totalTokens}`);
console.log(`Latency: ${stats.latencyMs}ms`);
// Go
response, stats, _ := aiClient.Chat().User("Hello").ExecuteWithStats(ctx)
fmt.Printf("Tokens: %d\n", stats.TotalTokens)
fmt.Printf("Latency: %dms\n", stats.LatencyMs)

The same code works across all providers:

// Just change the model identifier
let client = AiClient::new("anthropic/claude-3-5-sonnet").await?;
let client = AiClient::new("deepseek/deepseek-chat").await?;
let client = AiClient::new("gemini/gemini-2.0-flash").await?;
# Python - same pattern
client = await AiClient.create("anthropic/claude-3-5-sonnet")
client = await AiClient.create("deepseek/deepseek-chat")
client = await AiClient.create("gemini/gemini-2.0-flash")
// TypeScript - same pattern
const client = await AiClient.new('anthropic/claude-3-5-sonnet');
const client = await AiClient.new('deepseek/deepseek-chat');
const client = await AiClient.new('gemini/gemini-2.0-flash');
// Go - same pattern
aiClient, _ = client.NewAiClient(ctx, "anthropic", nil)
aiClient, _ = client.NewAiClient(ctx, "deepseek", nil)
aiClient, _ = client.NewAiClient(ctx, "gemini", nil)

The protocol manifest handles endpoint URLs, authentication, parameter mapping, and streaming format differences automatically.